bridge_channel.c File Reference

Bridging Channel API. More...

#include "asterisk.h"
#include <signal.h>
#include "asterisk/heap.h"
#include "asterisk/astobj2.h"
#include "asterisk/stringfields.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/timing.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_channel.h"
#include "asterisk/bridge_after.h"
#include "asterisk/bridge_channel_internal.h"
#include "asterisk/bridge_internal.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/musiconhold.h"
#include "asterisk/features_config.h"
#include "asterisk/parking.h"
#include "asterisk/causes.h"
#include "asterisk/test.h"
#include "asterisk/sem.h"

Include dependency graph for bridge_channel.c:

Go to the source code of this file.

Data Structures

struct  blind_transfer_data
 Data specifying where a blind transfer is going to. More...
struct  bridge_custom_callback
struct  bridge_park
struct  bridge_playfile
struct  bridge_run_app
struct  bridge_sync
 Synchronous bridge action object. More...
struct  sync_payload
 Frame payload for synchronous bridge actions. More...
struct  sync_structs
 List holding active synchronous action objects. More...

Defines

#define PLAYBACK_TIMEOUT   (600 * 1000)
 Failsafe for synchronous bridge action waiting.

Typedefs

typedef int(* ast_bridge_channel_post_action_data )(struct ast_bridge_channel *bridge_channel, enum bridge_channel_action_type action, const void *data, size_t datalen)
 Used to queue an action frame onto a bridge channel and write an action frame into a bridge.

Functions

static void __fini_sync_structs (void)
static void __init_sync_structs (void)
static void after_bridge_move_channel (struct ast_channel *chan_bridged, void *data)
static void after_bridge_move_channel_fail (enum ast_bridge_after_cb_reason reason, void *data)
void ast_bridge_channel_feature_digit (struct ast_bridge_channel *bridge_channel, int digit)
 Add a DTMF digit to the collected digits to match against DTMF features.
void ast_bridge_channel_feature_digit_add (struct ast_bridge_channel *bridge_channel, int digit)
 Add a DTMF digit to the collected digits.
void ast_bridge_channel_kick (struct ast_bridge_channel *bridge_channel, int cause)
 Kick the channel out of the bridge.
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).
void ast_bridge_channel_leave_bridge_nolock (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).
void ast_bridge_channel_lock_bridge (struct ast_bridge_channel *bridge_channel)
 Lock the bridge associated with the bridge channel.
struct ast_bridgeast_bridge_channel_merge_inhibit (struct ast_bridge_channel *bridge_channel, int request)
 Adjust the bridge_channel's bridge merge inhibit request count.
int ast_bridge_channel_notify_talking (struct ast_bridge_channel *bridge_channel, int started_talking)
 Lets the bridging indicate when a bridge channel has stopped or started talking.
struct ast_bridge_channelast_bridge_channel_peer (struct ast_bridge_channel *bridge_channel)
 Get the peer bridge channel of a two party bridge.
void ast_bridge_channel_playfile (struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
 Play a file on the bridge channel.
int ast_bridge_channel_queue_app (struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
 Queue a bridge action run application frame onto the bridge channel.
int ast_bridge_channel_queue_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)
 Queue a bridge action custom callback frame onto the bridge channel.
int ast_bridge_channel_queue_control_data (struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen)
 Queue a control frame onto the bridge channel with data.
int ast_bridge_channel_queue_frame (struct ast_bridge_channel *bridge_channel, struct ast_frame *fr)
 Write a frame to the specified bridge_channel.
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_bridge_channel_queue_playfile_sync (struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
 Synchronously queue a bridge action play file frame onto the bridge channel.
void ast_bridge_channel_restore_formats (struct ast_bridge_channel *bridge_channel)
 Restore the formats of a bridge channel's channel to how they were before bridge_channel_internal_join.
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.
void ast_bridge_channel_update_accountcodes (struct ast_bridge_channel *joining, struct ast_bridge_channel *leaving)
void ast_bridge_channel_update_linkedids (struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
int ast_bridge_channel_write_app (struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
 Write a bridge action run application frame into the bridge.
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.
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.
int ast_bridge_channel_write_hold (struct ast_bridge_channel *bridge_channel, const char *moh_class)
 Write a hold frame into the bridge.
int ast_bridge_channel_write_park (struct ast_bridge_channel *bridge_channel, const char *parkee_uuid, const char *parker_uuid, const char *app_data)
 Have a bridge channel park a channel in the bridge.
int ast_bridge_channel_write_playfile (struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
 Write a bridge action play file frame into the bridge.
int ast_bridge_channel_write_unhold (struct ast_bridge_channel *bridge_channel)
 Write an unhold frame into the bridge.
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.
static void bridge_channel_attended_transfer (struct ast_bridge_channel *bridge_channel, const char *target_chan_name)
static void bridge_channel_blind_transfer (struct ast_bridge_channel *bridge_channel, struct blind_transfer_data *blind_data)
static void bridge_channel_destroy (void *obj)
static void bridge_channel_dissolve_check (struct ast_bridge_channel *bridge_channel)
static void bridge_channel_do_callback (struct ast_bridge_channel *bridge_channel, struct bridge_custom_callback *data)
static void bridge_channel_dtmf_stream (struct ast_bridge_channel *bridge_channel, const char *dtmf)
 Internal function that plays back DTMF on a bridge channel.
static void bridge_channel_event_join_leave (struct ast_bridge_channel *bridge_channel, enum ast_bridge_hook_type type)
static int bridge_channel_feature_digit_add (struct ast_bridge_channel *bridge_channel, int digit, size_t dtmf_len)
static unsigned int bridge_channel_feature_digit_timeout (struct ast_bridge_channel *bridge_channel)
static int bridge_channel_feature_timeout (struct ast_bridge_channel *bridge_channel)
static void bridge_channel_handle_action (struct ast_bridge_channel *bridge_channel, enum bridge_channel_action_type action, void *data)
static void bridge_channel_handle_control (struct ast_bridge_channel *bridge_channel, struct ast_frame *fr)
static void bridge_channel_handle_feature_timeout (struct ast_bridge_channel *bridge_channel)
static void bridge_channel_handle_interval (struct ast_bridge_channel *bridge_channel)
static void bridge_channel_handle_write (struct ast_bridge_channel *bridge_channel)
struct ast_bridge_channelbridge_channel_internal_alloc (struct ast_bridge *bridge)
int bridge_channel_internal_allows_optimization (struct ast_bridge_channel *bridge_channel)
int bridge_channel_internal_join (struct ast_bridge_channel *bridge_channel)
void bridge_channel_internal_pull (struct ast_bridge_channel *bridge_channel)
int bridge_channel_internal_push (struct ast_bridge_channel *bridge_channel)
int bridge_channel_internal_queue_attended_transfer (struct ast_channel *transferee, struct ast_channel *unbridged_chan)
int bridge_channel_internal_queue_blind_transfer (struct ast_channel *transferee, const char *exten, const char *context, transfer_channel_cb new_channel_cb, void *user_data)
void bridge_channel_internal_suspend_nolock (struct ast_bridge_channel *bridge_channel)
void bridge_channel_internal_unsuspend_nolock (struct ast_bridge_channel *bridge_channel)
static int bridge_channel_next_interval (struct ast_bridge_channel *bridge_channel)
static int bridge_channel_next_timeout (struct ast_bridge_channel *bridge_channel)
static void bridge_channel_park (struct ast_bridge_channel *bridge_channel, struct bridge_park *payload)
static void bridge_channel_playfile (struct ast_bridge_channel *bridge_channel, struct bridge_playfile *payload)
static void bridge_channel_poke (struct ast_bridge_channel *bridge_channel)
static int bridge_channel_queue_action_data (struct ast_bridge_channel *bridge_channel, enum bridge_channel_action_type action, const void *data, size_t datalen)
static int bridge_channel_queue_action_data_sync (struct ast_bridge_channel *bridge_channel, enum bridge_channel_action_type action, const void *data, size_t datalen)
static void bridge_channel_read_wr_queue_alert (struct ast_bridge_channel *bridge_channel)
static void bridge_channel_run_app (struct ast_bridge_channel *bridge_channel, struct bridge_run_app *data)
void bridge_channel_settle_owed_events (struct ast_bridge *orig_bridge, struct ast_bridge_channel *bridge_channel)
static void bridge_channel_suspend (struct ast_bridge_channel *bridge_channel)
static void bridge_channel_talking (struct ast_bridge_channel *bridge_channel, int talking)
static void bridge_channel_unsuspend (struct ast_bridge_channel *bridge_channel)
static void bridge_channel_update_accountcodes_joining (struct ast_bridge_channel *joining, struct ast_bridge_channel *swap)
static void bridge_channel_update_accountcodes_leaving (struct ast_bridge_channel *leaving)
static void bridge_channel_wait (struct ast_bridge_channel *bridge_channel)
static int bridge_channel_write_action_data (struct ast_bridge_channel *bridge_channel, enum bridge_channel_action_type action, const void *data, size_t datalen)
static int bridge_channel_write_dtmf_stream (struct ast_bridge_channel *bridge_channel, const char *dtmf)
static int bridge_channel_write_frame (struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
static void bridge_frame_free (struct ast_frame *frame)
static struct ast_framebridge_handle_dtmf (struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 Internal function to handle DTMF from a channel.
static void bridge_handle_trip (struct ast_bridge_channel *bridge_channel)
static void bridge_sync_cleanup (struct bridge_sync *sync_struct)
 Clean up a syncrhonization bridge object.
static void bridge_sync_init (struct bridge_sync *sync_struct, unsigned int id)
 initialize a synchronous bridge object.
static void bridge_sync_signal (struct bridge_sync *sync_struct)
 Signal that waiting for a synchronous bridge action is no longer necessary.
static void bridge_sync_wait (struct bridge_sync *sync_struct)
 Wait for a synchronous bridge action to complete.
static void channel_fill_empty_accountcode (struct ast_channel *dest, struct ast_channel *src)
static void channel_fill_empty_peeraccount (struct ast_channel *dest, struct ast_channel *src)
static int channel_set_cause (struct ast_channel *chan, int cause)
static void channel_set_empty_accountcodes (struct ast_channel *c0, struct ast_channel *c1)
static void channel_update_peeraccount (struct ast_channel *dest, struct ast_channel *src)
static void channel_update_peeraccounts (struct ast_channel *c0, struct ast_channel *c1)
static int payload_helper_app (ast_bridge_channel_post_action_data post_it, struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
static int payload_helper_cb (ast_bridge_channel_post_action_data post_it, 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)
static int payload_helper_park (ast_bridge_channel_post_action_data post_it, struct ast_bridge_channel *bridge_channel, const char *parkee_uuid, const char *parker_uuid, const char *app_data)
static int payload_helper_playfile (ast_bridge_channel_post_action_data post_it, struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
static void pipe_close (int *my_pipe)
static int pipe_init_nonblock (int *my_pipe)
static int run_app_helper (struct ast_channel *chan, const char *app_name, const char *app_args)
static void testsuite_notify_feature_success (struct ast_channel *chan, const char *dtmf)

Variables

static int sync_ids
 Counter used for assigning synchronous bridge action IDs.


Detailed Description

Bridging Channel API.

Author:
Joshua Colp <jcolp@digium.com>

Richard Mudgett <rmudgett@digium.com>

Matt Jordan <mjordan@digium.com>

Definition in file bridge_channel.c.


Define Documentation

#define PLAYBACK_TIMEOUT   (600 * 1000)

Failsafe for synchronous bridge action waiting.

When waiting for a synchronous bridge action to complete, if there is a frame resource leak somewhere, it is possible that we will never get notified that the synchronous action completed.

If a significant amount of time passes, then we will abandon waiting for the synchrnous bridge action to complete.

This constant represents the number of milliseconds we will wait for the bridge action to complete.

Definition at line 177 of file bridge_channel.c.

Referenced by bridge_sync_wait().


Typedef Documentation

typedef int(* ast_bridge_channel_post_action_data)(struct ast_bridge_channel *bridge_channel, enum bridge_channel_action_type action, const void *data, size_t datalen)

Used to queue an action frame onto a bridge channel and write an action frame into a bridge.

Since:
12.0.0
Parameters:
bridge_channel Which channel work with.
action Type of bridge action frame.
data Frame payload data to pass.
datalen Frame payload data length to pass.
Return values:
0 on success.
-1 on error.

Definition at line 72 of file bridge_channel.c.


Function Documentation

static void __fini_sync_structs ( void   )  [static]

Definition at line 112 of file bridge_channel.c.

00124 {

static void __init_sync_structs ( void   )  [static]

Definition at line 112 of file bridge_channel.c.

00124 {

static void after_bridge_move_channel ( struct ast_channel chan_bridged,
void *  data 
) [static]

Definition at line 1744 of file bridge_channel.c.

References ao2_cleanup, ast_alloca, ast_channel_connected(), ast_channel_lock, ast_channel_move(), ast_channel_unlock, ast_connected_line_build_data(), AST_CONTROL_READ_ACTION, AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO, ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_party_id_reset(), ast_queue_control_data(), ast_softhangup(), AST_SOFTHANGUP_DEV, frame_size, NULL, ast_party_connected_line::priv, and RAII_VAR.

Referenced by bridge_channel_attended_transfer().

01745 {
01746    RAII_VAR(struct ast_channel *, chan_target, data, ao2_cleanup);
01747    struct ast_party_connected_line connected_target;
01748    unsigned char connected_line_data[1024];
01749    int payload_size;
01750 
01751    ast_party_connected_line_init(&connected_target);
01752 
01753    ast_channel_lock(chan_target);
01754    ast_party_connected_line_copy(&connected_target, ast_channel_connected(chan_target));
01755    ast_channel_unlock(chan_target);
01756    ast_party_id_reset(&connected_target.priv);
01757 
01758    if (ast_channel_move(chan_target, chan_bridged)) {
01759       ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
01760       ast_party_connected_line_free(&connected_target);
01761       return;
01762    }
01763 
01764    if ((payload_size = ast_connected_line_build_data(connected_line_data,
01765       sizeof(connected_line_data), &connected_target, NULL)) != -1) {
01766       struct ast_control_read_action_payload *frame_payload;
01767       int frame_size;
01768 
01769       frame_size = payload_size + sizeof(*frame_payload);
01770       frame_payload = ast_alloca(frame_size);
01771       frame_payload->action = AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO;
01772       frame_payload->payload_size = payload_size;
01773       memcpy(frame_payload->payload, connected_line_data, payload_size);
01774       ast_queue_control_data(chan_target, AST_CONTROL_READ_ACTION, frame_payload, frame_size);
01775    }
01776 
01777    ast_party_connected_line_free(&connected_target);
01778 }

static void after_bridge_move_channel_fail ( enum ast_bridge_after_cb_reason  reason,
void *  data 
) [static]

Definition at line 1784 of file bridge_channel.c.

References ao2_cleanup, ast_bridge_after_cb_reason_string(), ast_log, ast_softhangup(), AST_SOFTHANGUP_DEV, LOG_WARNING, and RAII_VAR.

Referenced by bridge_channel_attended_transfer().

01785 {
01786    RAII_VAR(struct ast_channel *, chan_target, data, ao2_cleanup);
01787 
01788    ast_log(LOG_WARNING, "Unable to complete transfer: %s\n",
01789       ast_bridge_after_cb_reason_string(reason));
01790    ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
01791 }

void ast_bridge_channel_feature_digit ( struct ast_bridge_channel bridge_channel,
int  digit 
)

Add a DTMF digit to the collected digits to match against DTMF features.

Since:
12.8.0
Parameters:
bridge_channel Channel that received a DTMF digit.
digit DTMF digit to add to collected digits or 0 for timeout event.
clear_digits clear the digits array prior to calling hooks
Note:
Neither the bridge nor the bridge_channel locks should be held when entering this function.

This is intended to be called by bridge hooks and the bridge channel thread.

This is intended to be called by non-DTMF bridge hooks and the bridge channel thread. Calling from a DTMF bridge hook can potentially cause unbounded recursion.

Returns:
Nothing

Definition at line 1563 of file bridge_channel.c.

References ao2_find, ao2_ref, ao2_unlink, ARRAY_LEN, ast_bridge_channel_kick(), ast_bridge_channel_lock_bridge(), ast_bridge_unlock, ast_channel_name(), ast_check_hangup_locked(), AST_CONTROL_SRCUPDATE, ast_debug, ast_indicate(), ast_samp2tv(), ast_test_suite_event_notify, ast_tvadd(), ast_tvnow(), ast_bridge_channel::bridge, bridge_channel_feature_digit_add(), bridge_channel_feature_digit_timeout(), bridge_channel_internal_suspend_nolock(), bridge_channel_unsuspend(), bridge_channel_write_dtmf_stream(), ast_bridge_hook::callback, ast_bridge_channel::chan, ast_bridge_hook_dtmf_parms::code, ast_bridge_channel::collected, ast_bridge_hook_dtmf::dtmf, ast_bridge_channel::dtmf_hook_state, ast_bridge_features::dtmf_hooks, ast_bridge_features::dtmf_passthrough, ast_bridge_channel::features, ast_bridge_hook_dtmf::generic, ast_bridge_hook::hook_pvt, ast_bridge_channel::interdigit_timeout, NULL, OBJ_SEARCH_PARTIAL_KEY, ast_bridge_channel::suspended, and testsuite_notify_feature_success().

Referenced by agent_alert(), bridge_channel_handle_feature_timeout(), bridge_channel_internal_join(), and bridge_handle_dtmf().

01564 {
01565    struct ast_bridge_features *features = bridge_channel->features;
01566    struct ast_bridge_hook_dtmf *hook = NULL;
01567    size_t dtmf_len;
01568 
01569    struct sanity_check_of_dtmf_size {
01570       char check[1 / (ARRAY_LEN(bridge_channel->dtmf_hook_state.collected) == ARRAY_LEN(hook->dtmf.code))];
01571    };
01572 
01573    dtmf_len = strlen(bridge_channel->dtmf_hook_state.collected);
01574    if (!dtmf_len && !digit) {
01575       /* Nothing to do */
01576       return;
01577    }
01578 
01579    if (digit) {
01580       dtmf_len = bridge_channel_feature_digit_add(bridge_channel, digit, dtmf_len);
01581    }
01582 
01583    while (digit) {
01584       /* See if a DTMF feature hook matches or can match */
01585       hook = ao2_find(features->dtmf_hooks, bridge_channel->dtmf_hook_state.collected,
01586          OBJ_SEARCH_PARTIAL_KEY);
01587       if (!hook) {
01588          ast_debug(1, "No DTMF feature hooks on %p(%s) match '%s'\n",
01589             bridge_channel, ast_channel_name(bridge_channel->chan),
01590             bridge_channel->dtmf_hook_state.collected);
01591          break;
01592       } else if (dtmf_len != strlen(hook->dtmf.code)) {
01593          unsigned int digit_timeout;
01594          /* Need more digits to match */
01595          ao2_ref(hook, -1);
01596          digit_timeout = bridge_channel_feature_digit_timeout(bridge_channel);
01597          bridge_channel->dtmf_hook_state.interdigit_timeout =
01598             ast_tvadd(ast_tvnow(), ast_samp2tv(digit_timeout, 1000));
01599          return;
01600       } else {
01601          int remove_me;
01602          int already_suspended;
01603 
01604          ast_debug(1, "DTMF feature hook %p matched DTMF string '%s' on %p(%s)\n",
01605             hook, bridge_channel->dtmf_hook_state.collected, bridge_channel,
01606             ast_channel_name(bridge_channel->chan));
01607 
01608          /*
01609           * Clear the collected digits before executing the hook
01610           * in case the hook starts another sequence.
01611           */
01612          bridge_channel->dtmf_hook_state.collected[0] = '\0';
01613 
01614          ast_bridge_channel_lock_bridge(bridge_channel);
01615          already_suspended = bridge_channel->suspended;
01616          if (!already_suspended) {
01617             bridge_channel_internal_suspend_nolock(bridge_channel);
01618          }
01619          ast_bridge_unlock(bridge_channel->bridge);
01620          ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01621 
01622          /* Execute the matched hook on this channel. */
01623          remove_me = hook->generic.callback(bridge_channel, hook->generic.hook_pvt);
01624          if (remove_me) {
01625             ast_debug(1, "DTMF hook %p is being removed from %p(%s)\n",
01626                hook, bridge_channel, ast_channel_name(bridge_channel->chan));
01627             ao2_unlink(features->dtmf_hooks, hook);
01628          }
01629          testsuite_notify_feature_success(bridge_channel->chan, hook->dtmf.code);
01630          ao2_ref(hook, -1);
01631 
01632          ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01633          if (!already_suspended) {
01634             bridge_channel_unsuspend(bridge_channel);
01635          }
01636 
01637          /*
01638           * If we are handing the channel off to an external hook for
01639           * ownership, we are not guaranteed what kind of state it will
01640           * come back in.  If the channel hungup, we need to detect that
01641           * here if the hook did not already change the state.
01642           */
01643          if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) {
01644             ast_bridge_channel_kick(bridge_channel, 0);
01645             bridge_channel->dtmf_hook_state.collected[0] = '\0';
01646             return;
01647          }
01648 
01649          /* if there is dtmf that has been collected then loop back through,
01650             but set digit to -1 so it doesn't try to do an add since the dtmf
01651             is already in the buffer */
01652          dtmf_len = strlen(bridge_channel->dtmf_hook_state.collected);
01653          if (!dtmf_len) {
01654             return;
01655          }
01656       }
01657    }
01658 
01659    if (!digit) {
01660       ast_debug(1, "DTMF feature string collection on %p(%s) timed out\n",
01661          bridge_channel, ast_channel_name(bridge_channel->chan));
01662    }
01663 
01664    /* Timeout or DTMF digit didn't allow a match with any hooks. */
01665    if (features->dtmf_passthrough) {
01666       /* Stream the collected DTMF to the other channels. */
01667       bridge_channel_write_dtmf_stream(bridge_channel,
01668          bridge_channel->dtmf_hook_state.collected);
01669    }
01670    bridge_channel->dtmf_hook_state.collected[0] = '\0';
01671 
01672    ast_test_suite_event_notify("FEATURE_DETECTION", "Result: fail");
01673 }

void ast_bridge_channel_feature_digit_add ( struct ast_bridge_channel bridge_channel,
int  digit 
)

Add a DTMF digit to the collected digits.

Since:
13.3.0
Parameters:
bridge_channel Channel that received a DTMF digit.
digit DTMF digit to add to collected digits
Note:
Neither the bridge nor the bridge_channel locks should be held when entering this function.

This is can only be called from within DTMF bridge hooks.

Definition at line 1555 of file bridge_channel.c.

References bridge_channel_feature_digit_add(), ast_bridge_channel::collected, and ast_bridge_channel::dtmf_hook_state.

Referenced by play_file().

01556 {
01557    if (digit) {
01558       bridge_channel_feature_digit_add(
01559          bridge_channel, digit, strlen(bridge_channel->dtmf_hook_state.collected));
01560    }
01561 }

void ast_bridge_channel_kick ( struct ast_bridge_channel bridge_channel,
int  cause 
)

Kick the channel out of the bridge.

Since:
12.0.0
Parameters:
bridge_channel Which channel is being kicked or hungup.
cause Cause of channel being kicked. If cause <= 0 then use cause on channel if cause still <= 0 use AST_CAUSE_NORMAL_CLEARING.
Note:
This is intended to be called by bridge hooks and the bridge channel thread.
Returns:
Nothing

Definition at line 589 of file bridge_channel.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ao2_unlink, ast_bridge_channel_leave_bridge(), ast_bridge_channel_lock, ast_bridge_channel_unlock, AST_BRIDGE_HOOK_TYPE_HANGUP, ast_channel_name(), ast_debug, BRIDGE_CHANNEL_STATE_END, BRIDGE_CHANNEL_STATE_WAIT, ast_bridge_hook::callback, ast_bridge_channel::chan, channel_set_cause(), ast_bridge_channel::features, ast_bridge_hook::hook_pvt, ast_bridge_features::other_hooks, ast_bridge_channel::state, and ast_bridge_hook::type.

Referenced by ast_bridge_channel_feature_digit(), ast_bridge_channel_run_app(), bridge_channel_attended_transfer(), bridge_channel_blind_transfer(), bridge_channel_internal_join(), bridge_handle_trip(), and kick_it().

00590 {
00591    struct ast_bridge_features *features = bridge_channel->features;
00592    struct ast_bridge_hook *hook;
00593    struct ao2_iterator iter;
00594 
00595    ast_bridge_channel_lock(bridge_channel);
00596    if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
00597       channel_set_cause(bridge_channel->chan, cause);
00598       cause = 0;
00599    }
00600    ast_bridge_channel_unlock(bridge_channel);
00601 
00602    /* Run any hangup hooks. */
00603    iter = ao2_iterator_init(features->other_hooks, 0);
00604    for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
00605       int remove_me;
00606 
00607       if (hook->type != AST_BRIDGE_HOOK_TYPE_HANGUP) {
00608          continue;
00609       }
00610       remove_me = hook->callback(bridge_channel, hook->hook_pvt);
00611       if (remove_me) {
00612          ast_debug(1, "Hangup hook %p is being removed from %p(%s)\n",
00613             hook, bridge_channel, ast_channel_name(bridge_channel->chan));
00614          ao2_unlink(features->other_hooks, hook);
00615       }
00616    }
00617    ao2_iterator_destroy(&iter);
00618 
00619    /* Default hangup action. */
00620    ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, cause);
00621 }

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).

Parameters:
bridge_channel Channel to change the state on
new_state The new state to place the channel into
cause Cause of channel leaving bridge. If cause <= 0 then use cause on channel if cause still <= 0 use AST_CAUSE_NORMAL_CLEARING.
Example usage:

This places the channel pointed to by bridge_channel into the state BRIDGE_CHANNEL_STATE_END if it was BRIDGE_CHANNEL_STATE_WAIT before.

Definition at line 298 of file bridge_channel.c.

References ast_bridge_channel_leave_bridge_nolock(), ast_bridge_channel_lock, and ast_bridge_channel_unlock.

Referenced by agent_connect_caller(), ast_bridge_channel_kick(), ast_bridge_depart(), ast_bridge_remove(), basic_hangup_hook(), bridge_agent_hold_heartbeat(), bridge_agent_hold_push(), bridge_channel_dissolve_check(), bridge_channel_internal_push(), bridge_dissolve(), bridge_do_merge(), bridge_do_move(), bridge_features_duration_callback(), bridge_stasis_push(), bridge_swap_attended_transfer(), bridgewait_timeout_callback(), caller_joined_bridge(), caller_safety_timeout(), feature_hangup(), parking_duration_callback(), say_parking_space(), and try_swap_optimize_out().

00299 {
00300    ast_bridge_channel_lock(bridge_channel);
00301    ast_bridge_channel_leave_bridge_nolock(bridge_channel, new_state, cause);
00302    ast_bridge_channel_unlock(bridge_channel);
00303 }

void ast_bridge_channel_leave_bridge_nolock ( 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).

Parameters:
bridge_channel Channel to change the state on
new_state The new state to place the channel into
cause Cause of channel leaving bridge. If cause <= 0 then use cause on channel if cause still <= 0 use AST_CAUSE_NORMAL_CLEARING.
Example usage:

This places the channel pointed to by bridge_channel into the state BRIDGE_CHANNEL_STATE_END if it was BRIDGE_CHANNEL_STATE_WAIT before.

Definition at line 280 of file bridge_channel.c.

References ast_channel_name(), ast_debug, bridge_channel_poke(), BRIDGE_CHANNEL_STATE_WAIT, ast_bridge_channel::chan, channel_set_cause(), and ast_bridge_channel::state.

Referenced by ast_bridge_channel_leave_bridge(), bridge_do_merge(), and caller_abort_agent().

00281 {
00282    if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
00283       return;
00284    }
00285 
00286    ast_debug(1, "Setting %p(%s) state from:%u to:%u\n",
00287       bridge_channel, ast_channel_name(bridge_channel->chan), bridge_channel->state,
00288       new_state);
00289 
00290    channel_set_cause(bridge_channel->chan, cause);
00291 
00292    /* Change the state on the bridge channel */
00293    bridge_channel->state = new_state;
00294 
00295    bridge_channel_poke(bridge_channel);
00296 }

void ast_bridge_channel_lock_bridge ( struct ast_bridge_channel bridge_channel  ) 

Lock the bridge associated with the bridge channel.

Since:
12.0.0
Parameters:
bridge_channel Channel that wants to lock the bridge.
This is an upstream lock operation. The defined locking order is bridge then bridge_channel.

Note:
On entry, neither the bridge nor bridge_channel is locked.

The bridge_channel->bridge pointer changes because of a bridge-merge/channel-move operation between bridges.

Returns:
Nothing

Definition at line 210 of file bridge_channel.c.

References ao2_ref, ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_bridge_lock, ast_bridge_unlock, and ast_bridge_channel::bridge.

Referenced by agent_alert(), ast_bridge_channel_feature_digit(), ast_bridge_channel_merge_inhibit(), ast_bridge_notify_masquerade(), basic_hangup_hook(), bridge_channel_internal_join(), bridge_channel_suspend(), bridge_channel_unsuspend(), bridge_channel_wait(), bridge_channel_write_frame(), deferred_action(), feature_automixmonitor(), feature_automonitor(), and parking_blind_transfer_park().

00211 {
00212    struct ast_bridge *bridge;
00213 
00214    for (;;) {
00215       /* Safely get the bridge pointer */
00216       ast_bridge_channel_lock(bridge_channel);
00217       bridge = bridge_channel->bridge;
00218       ao2_ref(bridge, +1);
00219       ast_bridge_channel_unlock(bridge_channel);
00220 
00221       /* Lock the bridge and see if it is still the bridge we need to lock. */
00222       ast_bridge_lock(bridge);
00223       if (bridge == bridge_channel->bridge) {
00224          ao2_ref(bridge, -1);
00225          return;
00226       }
00227       ast_bridge_unlock(bridge);
00228       ao2_ref(bridge, -1);
00229    }
00230 }

struct ast_bridge* ast_bridge_channel_merge_inhibit ( struct ast_bridge_channel bridge_channel,
int  request 
) [read]

Adjust the bridge_channel's bridge merge inhibit request count.

Since:
12.0.0
Parameters:
bridge_channel What to operate on.
request Inhibit request increment. (Positive to add requests. Negative to remove requests.)
Note:
This API call is meant for internal bridging operations.
Return values:
bridge adjusted merge inhibit with reference count.

Definition at line 353 of file bridge_channel.c.

References ao2_ref, ast_bridge_channel_lock_bridge(), ast_bridge_unlock, ast_bridge_channel::bridge, and bridge_merge_inhibit_nolock().

Referenced by feature_attended_transfer().

00354 {
00355    struct ast_bridge *bridge;
00356 
00357    ast_bridge_channel_lock_bridge(bridge_channel);
00358    bridge = bridge_channel->bridge;
00359    ao2_ref(bridge, +1);
00360    bridge_merge_inhibit_nolock(bridge, request);
00361    ast_bridge_unlock(bridge);
00362    return bridge;
00363 }

int ast_bridge_channel_notify_talking ( struct ast_bridge_channel bridge_channel,
int  started_talking 
)

Lets the bridging indicate when a bridge channel has stopped or started talking.

Note:
All DSP functionality on the bridge has been pushed down to the lowest possible layer, which in this case is the specific bridging technology being used. Since it is necessary for the knowledge of which channels are talking to make its way up to the application, this function has been created to allow the bridging technology to communicate that information with the bridging core.
Parameters:
bridge_channel The bridge channel that has either started or stopped talking.
started_talking set to 1 when this indicates the channel has started talking set to 0 when this indicates the channel has stopped talking.
Return values:
0 on success.
-1 on error.

Definition at line 232 of file bridge_channel.c.

References ast_bridge_channel_queue_frame(), AST_FRAME_BRIDGE_ACTION, BRIDGE_CHANNEL_ACTION_TALKING_START, BRIDGE_CHANNEL_ACTION_TALKING_STOP, and ast_frame::frametype.

Referenced by softmix_bridge_write_voice().

00233 {
00234    struct ast_frame action = {
00235       .frametype = AST_FRAME_BRIDGE_ACTION,
00236       .subclass.integer = started_talking
00237          ? BRIDGE_CHANNEL_ACTION_TALKING_START : BRIDGE_CHANNEL_ACTION_TALKING_STOP,
00238    };
00239 
00240    return ast_bridge_channel_queue_frame(bridge_channel, &action);
00241 }

struct ast_bridge_channel* ast_bridge_channel_peer ( struct ast_bridge_channel bridge_channel  )  [read]

Get the peer bridge channel of a two party bridge.

Since:
12.0.0
Parameters:
bridge_channel What to get the peer of.
Note:
On entry, bridge_channel->bridge is already locked.

This is an internal bridge function.

Return values:
peer on success.
NULL no peer channel.

Definition at line 305 of file bridge_channel.c.

References AST_LIST_TRAVERSE, ast_bridge_channel::bridge, ast_bridge::channels, ast_bridge_channel::in_bridge, NULL, and ast_bridge::num_channels.

Referenced by bridge_reconfigured_connected_line_update(), bridge_swap_attended_transfer(), parking_blind_transfer_park(), and try_swap_optimize_out().

00306 {
00307    struct ast_bridge *bridge = bridge_channel->bridge;
00308    struct ast_bridge_channel *other = NULL;
00309 
00310    if (bridge_channel->in_bridge && bridge->num_channels == 2) {
00311       AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
00312          if (other != bridge_channel) {
00313             break;
00314          }
00315       }
00316    }
00317 
00318    return other;
00319 }

void ast_bridge_channel_playfile ( struct ast_bridge_channel bridge_channel,
ast_bridge_custom_play_fn  custom_play,
const char *  playfile,
const char *  moh_class 
)

Play a file on the bridge channel.

Since:
12.0.0
Parameters:
bridge_channel Which channel to play the file on
custom_play Call this function to play the playfile. (NULL if normal sound file to play)
playfile Sound filename to play.
moh_class MOH class to request bridge peers to hear while file is played. NULL if no MOH. Empty if default MOH class.
Note:
This is intended to be called by bridge hooks.
Returns:
Nothing

Definition at line 1127 of file bridge_channel.c.

References ast_bridge_channel_write_hold(), ast_bridge_channel_write_unhold(), ast_channel_flags(), ast_channel_latest_musicclass(), ast_channel_lock, ast_channel_unlock, AST_DIGIT_NONE, AST_FLAG_MOH, ast_moh_start(), ast_strdupa, ast_stream_and_wait(), ast_test_flag, ast_bridge_channel::chan, and NULL.

Referenced by bridge_channel_playfile().

01128 {
01129    if (moh_class) {
01130       ast_bridge_channel_write_hold(bridge_channel, moh_class);
01131    }
01132    if (custom_play) {
01133       custom_play(bridge_channel, playfile);
01134    } else {
01135       ast_stream_and_wait(bridge_channel->chan, playfile, AST_DIGIT_NONE);
01136    }
01137    if (moh_class) {
01138       ast_bridge_channel_write_unhold(bridge_channel);
01139    }
01140 
01141    /*
01142     * It may be necessary to resume music on hold after we finish
01143     * playing the announcment.
01144     */
01145    if (ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_MOH)) {
01146       const char *latest_musicclass;
01147 
01148       ast_channel_lock(bridge_channel->chan);
01149       latest_musicclass = ast_strdupa(ast_channel_latest_musicclass(bridge_channel->chan));
01150       ast_channel_unlock(bridge_channel->chan);
01151       ast_moh_start(bridge_channel->chan, latest_musicclass, NULL);
01152    }
01153 }

int ast_bridge_channel_queue_app ( struct ast_bridge_channel bridge_channel,
const char *  app_name,
const char *  app_args,
const char *  moh_class 
)

Queue a bridge action run application frame onto the bridge channel.

Since:
12.0.0
Parameters:
bridge_channel Which channel to put the frame onto
app_name Dialplan application name.
app_args Arguments for the application. (NULL or empty for no arguments)
moh_class MOH class to request bridge peers to hear while application is running. NULL if no MOH. Empty if default MOH class.
Note:
This is intended to be called by bridge hooks.
Return values:
0 on success.
-1 on error.

Definition at line 1121 of file bridge_channel.c.

References bridge_channel_queue_action_data(), and payload_helper_app().

01122 {
01123    return payload_helper_app(bridge_channel_queue_action_data,
01124       bridge_channel, app_name, app_args, moh_class);
01125 }

int ast_bridge_channel_queue_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 
)

Queue a bridge action custom callback frame onto the bridge channel.

Since:
12.0.0
Parameters:
bridge_channel Which channel to put the frame onto.
flags Custom callback option flags.
callback Custom callback run on a bridge channel.
payload Data to pass to the callback. (NULL if none).
payload_size Size of the payload if payload is non-NULL. A number otherwise.
Note:
The payload MUST NOT have any resources that need to be freed.

This is intended to be called by bridge hooks.

Return values:
0 on success.
-1 on error.

Definition at line 1298 of file bridge_channel.c.

References bridge_channel_queue_action_data(), and payload_helper_cb().

Referenced by ast_bridge_kick(), defer_action(), handle_bridge_kick_channel(), and send_alert_to_agent().

01301 {
01302    return payload_helper_cb(bridge_channel_queue_action_data,
01303       bridge_channel, flags, callback, payload, payload_size);
01304 }

int ast_bridge_channel_queue_control_data ( struct ast_bridge_channel bridge_channel,
enum ast_control_frame_type  control,
const void *  data,
size_t  datalen 
)

Queue a control frame onto the bridge channel with data.

Since:
12.0.0
Parameters:
bridge_channel Which channel to queue the frame onto.
control Type of control frame.
data Frame payload data to pass.
datalen Frame payload data length to pass.
Return values:
0 on success.
-1 on error.

Definition at line 956 of file bridge_channel.c.

References ast_bridge_channel_queue_frame(), AST_FRAME_CONTROL, and ast_frame::frametype.

Referenced by bridge_reconfigured_connected_line_update(), send_colp_to_agent(), and softmix_src_change().

00957 {
00958    struct ast_frame frame = {
00959       .frametype = AST_FRAME_CONTROL,
00960       .subclass.integer = control,
00961       .datalen = datalen,
00962       .data.ptr = (void *) data,
00963    };
00964 
00965    return ast_bridge_channel_queue_frame(bridge_channel, &frame);
00966 }

int ast_bridge_channel_queue_frame ( struct ast_bridge_channel bridge_channel,
struct ast_frame fr 
)

Write a frame to the specified bridge_channel.

Since:
12.0.0
Parameters:
bridge_channel Channel to queue the frame.
fr Frame to write.
Return values:
0 on success.
-1 on error.

Definition at line 895 of file bridge_channel.c.

References ast_bridge_channel::alert_pipe, ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_channel_name(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_frdup(), ast_is_deferrable_frame(), AST_LIST_INSERT_TAIL, ast_log, BRIDGE_CHANNEL_STATE_WAIT, bridge_frame_free(), ast_bridge_channel::chan, ast_frame::frametype, LOG_ERROR, ast_bridge_channel::state, ast_bridge_channel::suspended, and ast_bridge_channel::wr_queue.

Referenced by ast_bridge_channel_notify_talking(), ast_bridge_channel_queue_control_data(), ast_bridge_queue_everyone_else(), bridge_channel_queue_action_data(), bridge_channel_queue_action_data_sync(), softmix_mixing_loop(), and softmix_pass_video_top_priority().

00896 {
00897    struct ast_frame *dup;
00898    char nudge = 0;
00899 
00900    if (bridge_channel->suspended
00901       /* Also defer DTMF frames. */
00902       && fr->frametype != AST_FRAME_DTMF_BEGIN
00903       && fr->frametype != AST_FRAME_DTMF_END
00904       && !ast_is_deferrable_frame(fr)) {
00905       /* Drop non-deferable frames when suspended. */
00906       return 0;
00907    }
00908    if (fr->frametype == AST_FRAME_NULL) {
00909       /* "Accept" the frame and discard it. */
00910       return 0;
00911    }
00912 
00913    dup = ast_frdup(fr);
00914    if (!dup) {
00915       return -1;
00916    }
00917 
00918    ast_bridge_channel_lock(bridge_channel);
00919    if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
00920       /* Drop frames on channels leaving the bridge. */
00921       ast_bridge_channel_unlock(bridge_channel);
00922       bridge_frame_free(dup);
00923       return 0;
00924    }
00925 
00926    AST_LIST_INSERT_TAIL(&bridge_channel->wr_queue, dup, frame_list);
00927    if (write(bridge_channel->alert_pipe[1], &nudge, sizeof(nudge)) != sizeof(nudge)) {
00928       ast_log(LOG_ERROR, "We couldn't write alert pipe for %p(%s)... something is VERY wrong\n",
00929          bridge_channel, ast_channel_name(bridge_channel->chan));
00930    }
00931    ast_bridge_channel_unlock(bridge_channel);
00932    return 0;
00933 }

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.

Since:
12.0.0
Parameters:
bridge_channel Which channel to put the frame onto.
custom_play Call this function to play the playfile. (NULL if normal sound file to play)
playfile Sound filename to play.
moh_class MOH class to request bridge peers to hear while file is played. NULL if no MOH. Empty if default MOH class.
Note:
This is intended to be called by bridge hooks.
Return values:
0 on success.
-1 on error.

Definition at line 1210 of file bridge_channel.c.

References bridge_channel_queue_action_data(), and payload_helper_playfile().

Referenced by ast_bridge_add_channel(), bridge_parking_pull(), bridge_parking_push(), check_bridge_play_sound(), feature_automixmonitor(), feature_automonitor(), parker_parked_call_message_response(), play_sound(), start_automixmonitor(), start_automonitor(), stop_automixmonitor(), and stop_automonitor().

01211 {
01212    return payload_helper_playfile(bridge_channel_queue_action_data,
01213       bridge_channel, custom_play, playfile, moh_class);
01214 }

int ast_bridge_channel_queue_playfile_sync ( struct ast_bridge_channel bridge_channel,
ast_bridge_custom_play_fn  custom_play,
const char *  playfile,
const char *  moh_class 
)

Synchronously queue a bridge action play file frame onto the bridge channel.

Since:
12.2.0
Parameters:
bridge_channel Which channel to put the frame onto.
custom_play Call this function to play the playfile. (NULL if normal sound file to play)
playfile Sound filename to play.
moh_class MOH class to request bridge peers to hear while file is played. NULL if no MOH. Empty if default MOH class.
This function will block until the queued frame has been destroyed. This will happen either if an error occurs or if the queued playback finishes.

Note:
No locks may be held when calling this function.
Return values:
0 The playback was successfully queued.
-1 The playback could not be queued.

Definition at line 1216 of file bridge_channel.c.

References bridge_channel_queue_action_data_sync(), and payload_helper_playfile().

Referenced by parker_parked_call_message_response(), and play_uri().

01218 {
01219    return payload_helper_playfile(bridge_channel_queue_action_data_sync,
01220       bridge_channel, custom_play, playfile, moh_class);
01221 }

void ast_bridge_channel_restore_formats ( struct ast_bridge_channel bridge_channel  ) 

Restore the formats of a bridge channel's channel to how they were before bridge_channel_internal_join.

Since:
12.0.0
Parameters:
bridge_channel Channel to restore

Definition at line 321 of file bridge_channel.c.

References ast_assert, ast_channel_lock, ast_channel_name(), ast_channel_readformat(), ast_channel_unlock, ast_channel_writeformat(), ast_debug, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_name(), ast_set_read_format(), ast_set_write_format(), ast_bridge_channel::chan, NULL, ast_bridge_channel::read_format, and ast_bridge_channel::write_format.

Referenced by bridge_channel_internal_join(), and participant_reaction_announcer_leave().

00322 {
00323    ast_assert(bridge_channel->read_format != NULL);
00324    ast_assert(bridge_channel->write_format != NULL);
00325 
00326    ast_channel_lock(bridge_channel->chan);
00327 
00328    /* Restore original formats of the channel as they came in */
00329    if (ast_format_cmp(ast_channel_readformat(bridge_channel->chan), bridge_channel->read_format) == AST_FORMAT_CMP_NOT_EQUAL) {
00330       ast_debug(1, "Bridge is returning %p(%s) to read format %s\n",
00331          bridge_channel, ast_channel_name(bridge_channel->chan),
00332          ast_format_get_name(bridge_channel->read_format));
00333       if (ast_set_read_format(bridge_channel->chan, bridge_channel->read_format)) {
00334          ast_debug(1, "Bridge failed to return %p(%s) to read format %s\n",
00335             bridge_channel, ast_channel_name(bridge_channel->chan),
00336             ast_format_get_name(bridge_channel->read_format));
00337       }
00338    }
00339    if (ast_format_cmp(ast_channel_writeformat(bridge_channel->chan), bridge_channel->write_format) == AST_FORMAT_CMP_NOT_EQUAL) {
00340       ast_debug(1, "Bridge is returning %p(%s) to write format %s\n",
00341          bridge_channel, ast_channel_name(bridge_channel->chan),
00342          ast_format_get_name(bridge_channel->write_format));
00343       if (ast_set_write_format(bridge_channel->chan, bridge_channel->write_format)) {
00344          ast_debug(1, "Bridge failed to return %p(%s) to write format %s\n",
00345             bridge_channel, ast_channel_name(bridge_channel->chan),
00346             ast_format_get_name(bridge_channel->write_format));
00347       }
00348    }
00349 
00350    ast_channel_unlock(bridge_channel->chan);
00351 }

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.

Since:
12.0.0
Parameters:
bridge_channel Which channel to run the application on.
app_name Dialplan application name.
app_args Arguments for the application. (NULL tolerant)
moh_class MOH class to request bridge peers to hear while application is running. NULL if no MOH. Empty if default MOH class.
Note:
This is intended to be called by bridge hooks.
Returns:
Nothing

Definition at line 1047 of file bridge_channel.c.

References ast_bridge_channel_kick(), ast_bridge_channel_write_hold(), ast_bridge_channel_write_unhold(), AST_CAUSE_NORMAL_CLEARING, ast_bridge_channel::chan, run_app_helper(), and S_OR.

Referenced by bridge_channel_run_app(), and dynamic_dtmf_hook_callback().

01048 {
01049    if (moh_class) {
01050       ast_bridge_channel_write_hold(bridge_channel, moh_class);
01051    }
01052    if (run_app_helper(bridge_channel->chan, app_name, S_OR(app_args, ""))) {
01053       /* Break the bridge if the app returns non-zero. */
01054       ast_bridge_channel_kick(bridge_channel, AST_CAUSE_NORMAL_CLEARING);
01055    }
01056    if (moh_class) {
01057       ast_bridge_channel_write_unhold(bridge_channel);
01058    }
01059 }

void ast_bridge_channel_update_accountcodes ( struct ast_bridge_channel joining,
struct ast_bridge_channel leaving 
)

void ast_bridge_channel_update_linkedids ( struct ast_bridge_channel bridge_channel,
struct ast_bridge_channel swap 
)

Definition at line 365 of file bridge_channel.c.

References ast_channel_internal_copy_linkedid(), ast_channel_internal_oldest_linkedid(), ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_bridge_channel::bridge, ast_bridge_channel::chan, and ast_bridge::channels.

Referenced by bridge_basic_push(), and bridge_stasis_push().

00366 {
00367    struct ast_bridge_channel *other;
00368    struct ast_bridge *bridge = bridge_channel->bridge;
00369    struct ast_channel *oldest_linkedid_chan = bridge_channel->chan;
00370 
00371    AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
00372       if (other == swap) {
00373          continue;
00374       }
00375       oldest_linkedid_chan = ast_channel_internal_oldest_linkedid(
00376          oldest_linkedid_chan, other->chan);
00377    }
00378 
00379    ast_channel_lock(bridge_channel->chan);
00380    ast_channel_internal_copy_linkedid(bridge_channel->chan, oldest_linkedid_chan);
00381    ast_channel_unlock(bridge_channel->chan);
00382    AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
00383       if (other == swap) {
00384          continue;
00385       }
00386       ast_channel_lock(other->chan);
00387       ast_channel_internal_copy_linkedid(other->chan, oldest_linkedid_chan);
00388       ast_channel_unlock(other->chan);
00389    }
00390 }

int ast_bridge_channel_write_app ( struct ast_bridge_channel bridge_channel,
const char *  app_name,
const char *  app_args,
const char *  moh_class 
)

Write a bridge action run application frame into the bridge.

Since:
12.0.0
Parameters:
bridge_channel Which channel is putting the frame into the bridge
app_name Dialplan application name.
app_args Arguments for the application. (NULL or empty for no arguments)
moh_class MOH class to request bridge peers to hear while application is running. NULL if no MOH. Empty if default MOH class.
Note:
This is intended to be called by bridge hooks.
Return values:
0 on success.
-1 on error.

Definition at line 1115 of file bridge_channel.c.

References bridge_channel_write_action_data(), and payload_helper_app().

01116 {
01117    return payload_helper_app(bridge_channel_write_action_data,
01118       bridge_channel, app_name, app_args, moh_class);
01119 }

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.

Since:
12.0.0
Parameters:
bridge_channel Which channel is putting the frame into the bridge
flags Custom callback option flags.
callback Custom callback run on a bridge channel.
payload Data to pass to the callback. (NULL if none).
payload_size Size of the payload if payload is non-NULL. A number otherwise.
Note:
The payload MUST NOT have any resources that need to be freed.

This is intended to be called by bridge hooks.

Return values:
0 on success.
-1 on error.

Definition at line 1290 of file bridge_channel.c.

References bridge_channel_write_action_data(), and payload_helper_cb().

Referenced by agent_connect_caller(), and dynamic_dtmf_hook_trip().

01293 {
01294    return payload_helper_cb(bridge_channel_write_action_data,
01295       bridge_channel, flags, callback, payload, payload_size);
01296 }

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.

Since:
12.0.0
Parameters:
bridge_channel Which channel is putting the frame into the bridge.
control Type of control frame.
data Frame payload data to pass.
datalen Frame payload data length to pass.
Return values:
0 on success.
-1 on error.

Definition at line 968 of file bridge_channel.c.

References AST_FRAME_CONTROL, bridge_channel_write_frame(), and ast_frame::frametype.

Referenced by agent_connect_caller(), ast_bridge_channel_write_hold(), ast_bridge_channel_write_unhold(), and ringing().

00969 {
00970    struct ast_frame frame = {
00971       .frametype = AST_FRAME_CONTROL,
00972       .subclass.integer = control,
00973       .datalen = datalen,
00974       .data.ptr = (void *) data,
00975    };
00976 
00977    return bridge_channel_write_frame(bridge_channel, &frame);
00978 }

int ast_bridge_channel_write_hold ( struct ast_bridge_channel bridge_channel,
const char *  moh_class 
)

Write a hold frame into the bridge.

Since:
12.0.0
Parameters:
bridge_channel Which channel is putting the hold into the bridge.
moh_class The suggested music class for the other end to use.
Return values:
0 on success.
-1 on error.

Definition at line 980 of file bridge_channel.c.

References ast_bridge_channel_write_control_data(), ast_channel_hold_type(), ast_channel_publish_cached_blob(), AST_CONTROL_HOLD, ast_json_pack(), ast_json_unref(), ast_strlen_zero, ast_bridge_channel::chan, and NULL.

Referenced by ast_bridge_channel_playfile(), ast_bridge_channel_run_app(), feature_attended_transfer(), feature_blind_transfer(), and hold().

00981 {
00982    struct ast_json *blob;
00983    int res;
00984    size_t datalen;
00985 
00986    if (!ast_strlen_zero(moh_class)) {
00987       datalen = strlen(moh_class) + 1;
00988 
00989       blob = ast_json_pack("{s: s}",
00990          "musicclass", moh_class);
00991    } else {
00992       moh_class = NULL;
00993       datalen = 0;
00994       blob = NULL;
00995    }
00996 
00997    ast_channel_publish_cached_blob(bridge_channel->chan, ast_channel_hold_type(), blob);
00998 
00999    res = ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD,
01000       moh_class, datalen);
01001 
01002    ast_json_unref(blob);
01003    return res;
01004 }

int ast_bridge_channel_write_park ( struct ast_bridge_channel bridge_channel,
const char *  parkee_uuid,
const char *  parker_uuid,
const char *  app_data 
)

Have a bridge channel park a channel in the bridge.

Since:
12.0.0
Parameters:
bridge_channel Bridge channel performing the parking
parkee_uuid Unique id of the channel we want to park
parker_uuid Unique id of the channel parking the call
app_data string indicating data used for park application (NULL allowed)
Note:
This is intended to be called by bridge hooks.
Return values:
0 on success.
-1 on error.

Definition at line 1361 of file bridge_channel.c.

References bridge_channel_write_action_data(), and payload_helper_park().

Referenced by manager_park_bridged(), and parking_blind_transfer_park().

01362 {
01363    return payload_helper_park(bridge_channel_write_action_data,
01364       bridge_channel, parkee_uuid, parker_uuid, app_data);
01365 }

int ast_bridge_channel_write_playfile ( struct ast_bridge_channel bridge_channel,
ast_bridge_custom_play_fn  custom_play,
const char *  playfile,
const char *  moh_class 
)

Write a bridge action play file frame into the bridge.

Since:
12.0.0
Parameters:
bridge_channel Which channel is putting the frame into the bridge
custom_play Call this function to play the playfile. (NULL if normal sound file to play)
playfile Sound filename to play.
moh_class MOH class to request bridge peers to hear while file is played. NULL if no MOH. Empty if default MOH class.
Note:
This is intended to be called by bridge hooks.
Return values:
0 on success.
-1 on error.

Definition at line 1204 of file bridge_channel.c.

References bridge_channel_write_action_data(), and payload_helper_playfile().

Referenced by ast_bridge_transfer_attended(), start_automixmonitor(), start_automonitor(), stop_automixmonitor(), and stop_automonitor().

01205 {
01206    return payload_helper_playfile(bridge_channel_write_action_data,
01207       bridge_channel, custom_play, playfile, moh_class);
01208 }

int ast_bridge_channel_write_unhold ( struct ast_bridge_channel bridge_channel  ) 

Write an unhold frame into the bridge.

Since:
12.0.0
Parameters:
bridge_channel Which channel is putting the hold into the bridge.
Return values:
0 on success.
-1 on error.

Definition at line 1006 of file bridge_channel.c.

References ast_bridge_channel_write_control_data(), ast_channel_publish_cached_blob(), ast_channel_unhold_type(), AST_CONTROL_UNHOLD, ast_bridge_channel::chan, and NULL.

Referenced by ast_bridge_channel_playfile(), ast_bridge_channel_run_app(), ast_bridge_transfer_attended(), ast_bridge_transfer_blind(), feature_attended_transfer(), feature_blind_transfer(), and unhold().

01007 {
01008    ast_channel_publish_cached_blob(bridge_channel->chan, ast_channel_unhold_type(), NULL);
01009 
01010    return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
01011 }

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.

Since:
12.0.0
Parameters:
bridge What bridge to distribute frame.
bridge_channel Channel to optionally not pass frame to. (NULL to pass to everyone)
frame Frame to pass.
Note:
This is intended to be called by bridge hooks and bridge technologies.
Return values:
0 Frame written to at least one channel.
-1 Frame written to no channels.

Definition at line 935 of file bridge_channel.c.

References ast_bridge_channel_queue_frame(), AST_FRAME_NULL, AST_LIST_TRAVERSE, ast_bridge::channels, and ast_frame::frametype.

Referenced by bridge_hold(), bridge_ringing(), bridge_unhold(), holding_bridge_write(), native_bridge_write(), native_rtp_bridge_write(), simple_bridge_write(), softmix_bridge_write(), and softmix_bridge_write_video().

00936 {
00937    struct ast_bridge_channel *cur;
00938    int not_written = -1;
00939 
00940    if (frame->frametype == AST_FRAME_NULL) {
00941       /* "Accept" the frame and discard it. */
00942       return 0;
00943    }
00944 
00945    AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
00946       if (cur == bridge_channel) {
00947          continue;
00948       }
00949       if (!ast_bridge_channel_queue_frame(cur, frame)) {
00950          not_written = 0;
00951       }
00952    }
00953    return not_written;
00954 }

static void bridge_channel_attended_transfer ( struct ast_bridge_channel bridge_channel,
const char *  target_chan_name 
) [static]

Definition at line 1808 of file bridge_channel.c.

References after_bridge_move_channel(), after_bridge_move_channel_fail(), ao2_cleanup, ao2_ref, ast_assert, ast_bridge_channel_kick(), ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_bridge_set_after_callback(), AST_CAUSE_NORMAL_CLEARING, ast_channel_get_by_name(), ast_channel_ref, ast_channel_unref, ast_softhangup(), AST_SOFTHANGUP_DEV, ast_bridge_channel::chan, NULL, and RAII_VAR.

Referenced by bridge_channel_handle_action().

01810 {
01811    RAII_VAR(struct ast_channel *, chan_target, NULL, ao2_cleanup);
01812    RAII_VAR(struct ast_channel *, chan_bridged, NULL, ao2_cleanup);
01813 
01814    chan_target = ast_channel_get_by_name(target_chan_name);
01815    if (!chan_target) {
01816       /* Dang, it disappeared somehow */
01817       ast_bridge_channel_kick(bridge_channel, AST_CAUSE_NORMAL_CLEARING);
01818       return;
01819    }
01820 
01821    ast_bridge_channel_lock(bridge_channel);
01822    chan_bridged = bridge_channel->chan;
01823    ast_assert(chan_bridged != NULL);
01824    ao2_ref(chan_bridged, +1);
01825    ast_bridge_channel_unlock(bridge_channel);
01826 
01827    if (ast_bridge_set_after_callback(chan_bridged, after_bridge_move_channel,
01828       after_bridge_move_channel_fail, ast_channel_ref(chan_target))) {
01829       ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
01830 
01831       /* Release the ref we tried to pass to ast_bridge_set_after_callback(). */
01832       ast_channel_unref(chan_target);
01833    }
01834    ast_bridge_channel_kick(bridge_channel, AST_CAUSE_NORMAL_CLEARING);
01835 }

static void bridge_channel_blind_transfer ( struct ast_bridge_channel bridge_channel,
struct blind_transfer_data blind_data 
) [static]

static void bridge_channel_destroy ( void *  obj  )  [static]

Definition at line 2793 of file bridge_channel.c.

References ast_bridge_channel::alert_pipe, ao2_cleanup, ao2_ref, ast_cond_destroy, AST_LIST_REMOVE_HEAD, ast_bridge_channel::bridge, bridge_frame_free(), ast_bridge_channel::callid, ast_bridge_channel::cond, NULL, pipe_close(), ast_bridge_channel::read_format, ast_bridge_channel::wr_queue, and ast_bridge_channel::write_format.

Referenced by bridge_channel_internal_alloc().

02794 {
02795    struct ast_bridge_channel *bridge_channel = obj;
02796    struct ast_frame *fr;
02797 
02798    if (bridge_channel->callid) {
02799       bridge_channel->callid = 0;
02800    }
02801 
02802    if (bridge_channel->bridge) {
02803       ao2_ref(bridge_channel->bridge, -1);
02804       bridge_channel->bridge = NULL;
02805    }
02806 
02807    /* Flush any unhandled wr_queue frames. */
02808    while ((fr = AST_LIST_REMOVE_HEAD(&bridge_channel->wr_queue, frame_list))) {
02809       bridge_frame_free(fr);
02810    }
02811    pipe_close(bridge_channel->alert_pipe);
02812 
02813    ast_cond_destroy(&bridge_channel->cond);
02814 
02815    ao2_cleanup(bridge_channel->write_format);
02816    ao2_cleanup(bridge_channel->read_format);
02817 }

static void bridge_channel_dissolve_check ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 1910 of file bridge_channel.c.

References AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP, ast_bridge_channel_leave_bridge(), AST_BRIDGE_FLAG_DISSOLVE_EMPTY, AST_BRIDGE_FLAG_DISSOLVE_HANGUP, ast_channel_hangupcause(), AST_LIST_FIRST, ast_test_flag, ast_bridge_channel::bridge, BRIDGE_CHANNEL_STATE_END, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_dissolve(), ast_bridge_channel::chan, ast_bridge::channels, ast_bridge::dissolved, ast_bridge_features::feature_flags, ast_bridge::feature_flags, ast_bridge_channel::features, ast_bridge::num_channels, ast_bridge::num_lonely, ast_bridge_channel::state, and ast_bridge_features::usable.

Referenced by bridge_channel_internal_join(), and bridge_channel_internal_pull().

01911 {
01912    struct ast_bridge *bridge = bridge_channel->bridge;
01913 
01914    if (bridge->dissolved) {
01915       return;
01916    }
01917 
01918    if (!bridge->num_channels
01919       && ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_EMPTY)) {
01920       /* Last channel leaving the bridge turns off the lights. */
01921       bridge_dissolve(bridge, ast_channel_hangupcause(bridge_channel->chan));
01922       return;
01923    }
01924 
01925    switch (bridge_channel->state) {
01926    case BRIDGE_CHANNEL_STATE_END:
01927       /* Do we need to dissolve the bridge because this channel hung up? */
01928       if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_HANGUP)
01929          || (bridge_channel->features->usable
01930             && ast_test_flag(&bridge_channel->features->feature_flags,
01931                AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP))) {
01932          bridge_dissolve(bridge, ast_channel_hangupcause(bridge_channel->chan));
01933          return;
01934       }
01935       break;
01936    default:
01937       break;
01938    }
01939 
01940    if (bridge->num_lonely && bridge->num_lonely == bridge->num_channels) {
01941       /*
01942        * This will start a chain reaction where each channel leaving
01943        * enters this function and causes the next to leave as long as
01944        * there aren't non-lonely channels in the bridge.
01945        */
01946       ast_bridge_channel_leave_bridge(AST_LIST_FIRST(&bridge->channels),
01947          BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE,
01948          ast_channel_hangupcause(bridge_channel->chan));
01949    }
01950 }

static void bridge_channel_do_callback ( struct ast_bridge_channel bridge_channel,
struct bridge_custom_callback data 
) [static]

static void bridge_channel_dtmf_stream ( struct ast_bridge_channel bridge_channel,
const char *  dtmf 
) [static]

Internal function that plays back DTMF on a bridge channel.

Definition at line 1727 of file bridge_channel.c.

References ast_channel_name(), ast_debug, ast_dtmf_stream(), ast_bridge_channel::chan, and NULL.

Referenced by bridge_channel_handle_action().

01728 {
01729    ast_debug(1, "Playing DTMF stream '%s' out to %p(%s)\n",
01730       dtmf, bridge_channel, ast_channel_name(bridge_channel->chan));
01731    ast_dtmf_stream(bridge_channel->chan, NULL, dtmf, 0, 0);
01732 }

static void bridge_channel_event_join_leave ( struct ast_bridge_channel bridge_channel,
enum ast_bridge_hook_type  type 
) [static]

Definition at line 2513 of file bridge_channel.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ao2_unlink, AST_CONTROL_SRCUPDATE, ast_indicate(), bridge_channel_suspend(), bridge_channel_unsuspend(), ast_bridge_hook::callback, ast_bridge_channel::chan, ast_bridge_channel::features, ast_bridge_hook::hook_pvt, ast_bridge_features::other_hooks, and ast_bridge_hook::type.

Referenced by bridge_channel_internal_join().

02514 {
02515    struct ast_bridge_features *features = bridge_channel->features;
02516    struct ast_bridge_hook *hook;
02517    struct ao2_iterator iter;
02518 
02519    /* Run the specified hooks. */
02520    iter = ao2_iterator_init(features->other_hooks, 0);
02521    for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
02522       if (hook->type == type) {
02523          break;
02524       }
02525    }
02526    if (hook) {
02527       /* Found the first specified hook to run. */
02528       bridge_channel_suspend(bridge_channel);
02529       ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
02530       do {
02531          if (hook->type == type) {
02532             hook->callback(bridge_channel, hook->hook_pvt);
02533             ao2_unlink(features->other_hooks, hook);
02534          }
02535          ao2_ref(hook, -1);
02536       } while ((hook = ao2_iterator_next(&iter)));
02537       ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
02538       bridge_channel_unsuspend(bridge_channel);
02539    }
02540    ao2_iterator_destroy(&iter);
02541 }

static int bridge_channel_feature_digit_add ( struct ast_bridge_channel bridge_channel,
int  digit,
size_t  dtmf_len 
) [static]

Definition at line 1518 of file bridge_channel.c.

References ARRAY_LEN, ast_channel_name(), ast_debug, ast_bridge_channel::chan, ast_bridge_channel::collected, and ast_bridge_channel::dtmf_hook_state.

Referenced by ast_bridge_channel_feature_digit(), and ast_bridge_channel_feature_digit_add().

01520 {
01521    if (dtmf_len < ARRAY_LEN(bridge_channel->dtmf_hook_state.collected) - 1) {
01522       /* Add the new digit to the DTMF string so we can do our matching */
01523       bridge_channel->dtmf_hook_state.collected[dtmf_len++] = digit;
01524       bridge_channel->dtmf_hook_state.collected[dtmf_len] = '\0';
01525 
01526       ast_debug(1, "DTMF feature string on %p(%s) is now '%s'\n",
01527            bridge_channel, ast_channel_name(bridge_channel->chan),
01528            bridge_channel->dtmf_hook_state.collected);
01529    }
01530 
01531    return dtmf_len;
01532 }

static unsigned int bridge_channel_feature_digit_timeout ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 1534 of file bridge_channel.c.

References ao2_ref, ast_channel_lock, ast_channel_unlock, ast_get_chan_features_general_config(), ast_log, ast_bridge_channel::chan, ast_features_general_config::featuredigittimeout, and LOG_ERROR.

Referenced by ast_bridge_channel_feature_digit().

01535 {
01536    unsigned int digit_timeout;
01537    struct ast_features_general_config *gen_cfg;
01538 
01539    /* Determine interdigit timeout */
01540    ast_channel_lock(bridge_channel->chan);
01541    gen_cfg = ast_get_chan_features_general_config(bridge_channel->chan);
01542    ast_channel_unlock(bridge_channel->chan);
01543 
01544    if (!gen_cfg) {
01545       ast_log(LOG_ERROR, "Unable to retrieve features configuration.\n");
01546       return 3000; /* Pick a reasonable failsafe timeout in ms */
01547    }
01548 
01549    digit_timeout = gen_cfg->featuredigittimeout;
01550    ao2_ref(gen_cfg, -1);
01551 
01552    return digit_timeout;
01553 }

static int bridge_channel_feature_timeout ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 2394 of file bridge_channel.c.

References ast_tvdiff_ms(), ast_tvnow(), ast_bridge_channel::collected, ast_bridge_channel::dtmf_hook_state, and ast_bridge_channel::interdigit_timeout.

Referenced by bridge_channel_next_timeout().

02395 {
02396    int ms;
02397 
02398    if (bridge_channel->dtmf_hook_state.collected[0]) {
02399       ms = ast_tvdiff_ms(bridge_channel->dtmf_hook_state.interdigit_timeout,
02400          ast_tvnow());
02401       if (ms < 0) {
02402          /* Expire immediately. */
02403          ms = 0;
02404       }
02405    } else {
02406       /* Timer is not active so wait forever. */
02407       ms = -1;
02408    }
02409 
02410    return ms;
02411 }

static void bridge_channel_handle_action ( struct ast_bridge_channel bridge_channel,
enum bridge_channel_action_type  action,
void *  data 
) [static]

Definition at line 1848 of file bridge_channel.c.

References AST_CONTROL_SRCUPDATE, ast_indicate(), BRIDGE_CHANNEL_ACTION_ATTENDED_TRANSFER, BRIDGE_CHANNEL_ACTION_BLIND_TRANSFER, BRIDGE_CHANNEL_ACTION_CALLBACK, BRIDGE_CHANNEL_ACTION_DTMF_STREAM, BRIDGE_CHANNEL_ACTION_PARK, BRIDGE_CHANNEL_ACTION_PLAY_FILE, BRIDGE_CHANNEL_ACTION_RUN_APP, BRIDGE_CHANNEL_ACTION_TALKING_START, BRIDGE_CHANNEL_ACTION_TALKING_STOP, bridge_channel_attended_transfer(), bridge_channel_blind_transfer(), bridge_channel_do_callback(), bridge_channel_dtmf_stream(), bridge_channel_park(), bridge_channel_playfile(), bridge_channel_run_app(), bridge_channel_suspend(), bridge_channel_talking(), bridge_channel_unsuspend(), and ast_bridge_channel::chan.

Referenced by bridge_channel_handle_write().

01850 {
01851    switch (action) {
01852    case BRIDGE_CHANNEL_ACTION_DTMF_STREAM:
01853       bridge_channel_suspend(bridge_channel);
01854       ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01855       bridge_channel_dtmf_stream(bridge_channel, data);
01856       ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01857       bridge_channel_unsuspend(bridge_channel);
01858       break;
01859    case BRIDGE_CHANNEL_ACTION_TALKING_START:
01860    case BRIDGE_CHANNEL_ACTION_TALKING_STOP:
01861       bridge_channel_talking(bridge_channel,
01862          action == BRIDGE_CHANNEL_ACTION_TALKING_START);
01863       break;
01864    case BRIDGE_CHANNEL_ACTION_PLAY_FILE:
01865       bridge_channel_suspend(bridge_channel);
01866       ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01867       bridge_channel_playfile(bridge_channel, data);
01868       ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01869       bridge_channel_unsuspend(bridge_channel);
01870       break;
01871    case BRIDGE_CHANNEL_ACTION_RUN_APP:
01872       bridge_channel_suspend(bridge_channel);
01873       ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01874       bridge_channel_run_app(bridge_channel, data);
01875       ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01876       bridge_channel_unsuspend(bridge_channel);
01877       break;
01878    case BRIDGE_CHANNEL_ACTION_CALLBACK:
01879       bridge_channel_do_callback(bridge_channel, data);
01880       break;
01881    case BRIDGE_CHANNEL_ACTION_PARK:
01882       bridge_channel_suspend(bridge_channel);
01883       ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01884       bridge_channel_park(bridge_channel, data);
01885       ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01886       bridge_channel_unsuspend(bridge_channel);
01887       break;
01888    case BRIDGE_CHANNEL_ACTION_BLIND_TRANSFER:
01889       bridge_channel_blind_transfer(bridge_channel, data);
01890       break;
01891    case BRIDGE_CHANNEL_ACTION_ATTENDED_TRANSFER:
01892       bridge_channel_attended_transfer(bridge_channel, data);
01893       break;
01894    default:
01895       break;
01896    }
01897 }

static void bridge_channel_handle_control ( struct ast_bridge_channel bridge_channel,
struct ast_frame fr 
) [static]

Definition at line 2094 of file bridge_channel.c.

References ast_answer(), ast_assert, ast_channel_connected_line_macro(), ast_channel_connected_line_sub(), ast_channel_flags(), ast_channel_redirecting_macro(), ast_channel_redirecting_sub(), ast_channel_setoption(), AST_CONTROL_ANSWER, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_MASQUERADE_NOTIFY, AST_CONTROL_OPTION, AST_CONTROL_REDIRECTING, AST_FLAG_OUTGOING, ast_indicate(), ast_indicate_data(), AST_OPTION_AUDIO_MODE, AST_OPTION_DIGIT_DETECT, AST_OPTION_FAX_DETECT, AST_OPTION_FLAG_REQUEST, AST_OPTION_RELAXDTMF, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_STATE_UP, ast_test_flag, ast_bridge_channel::chan, ast_option_header::data, ast_frame::data, ast_frame::datalen, ast_frame_subclass::integer, NULL, ast_frame::ptr, and ast_frame::subclass.

Referenced by bridge_channel_handle_write().

02095 {
02096    struct ast_channel *chan;
02097    struct ast_option_header *aoh;
02098    int is_caller;
02099 
02100    chan = bridge_channel->chan;
02101    switch (fr->subclass.integer) {
02102    case AST_CONTROL_REDIRECTING:
02103       is_caller = !ast_test_flag(ast_channel_flags(chan), AST_FLAG_OUTGOING);
02104       if (ast_channel_redirecting_sub(NULL, chan, fr, 1) &&
02105          ast_channel_redirecting_macro(NULL, chan, fr, is_caller, 1)) {
02106          ast_indicate_data(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);
02107       }
02108       break;
02109    case AST_CONTROL_CONNECTED_LINE:
02110       is_caller = !ast_test_flag(ast_channel_flags(chan), AST_FLAG_OUTGOING);
02111       if (ast_channel_connected_line_sub(NULL, chan, fr, 1) &&
02112          ast_channel_connected_line_macro(NULL, chan, fr, is_caller, 1)) {
02113          ast_indicate_data(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);
02114       }
02115       break;
02116    case AST_CONTROL_OPTION:
02117       /*
02118        * Forward option Requests, but only ones we know are safe These
02119        * are ONLY sent by chan_iax2 and I'm not convinced that they
02120        * are useful. I haven't deleted them entirely because I just am
02121        * not sure of the ramifications of removing them.
02122        */
02123       aoh = fr->data.ptr;
02124       if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
02125          switch (ntohs(aoh->option)) {
02126          case AST_OPTION_TONE_VERIFY:
02127          case AST_OPTION_TDD:
02128          case AST_OPTION_RELAXDTMF:
02129          case AST_OPTION_AUDIO_MODE:
02130          case AST_OPTION_DIGIT_DETECT:
02131          case AST_OPTION_FAX_DETECT:
02132             ast_channel_setoption(chan, ntohs(aoh->option), aoh->data,
02133                fr->datalen - sizeof(*aoh), 0);
02134             break;
02135          default:
02136             break;
02137          }
02138       }
02139       break;
02140    case AST_CONTROL_ANSWER:
02141       if (ast_channel_state(chan) != AST_STATE_UP) {
02142          ast_answer(chan);
02143       } else {
02144          ast_indicate(chan, -1);
02145       }
02146       break;
02147    case AST_CONTROL_MASQUERADE_NOTIFY:
02148       /* Should never happen. */
02149       ast_assert(0);
02150       break;
02151    default:
02152       ast_indicate_data(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);
02153       break;
02154    }
02155 }

static void bridge_channel_handle_feature_timeout ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 1684 of file bridge_channel.c.

References ast_bridge_channel_feature_digit(), ast_tvdiff_ms(), ast_tvnow(), ast_bridge_channel::collected, ast_bridge_channel::dtmf_hook_state, and ast_bridge_channel::interdigit_timeout.

Referenced by bridge_channel_wait().

01685 {
01686    if (!bridge_channel->dtmf_hook_state.collected[0]
01687       || 0 < ast_tvdiff_ms(bridge_channel->dtmf_hook_state.interdigit_timeout,
01688          ast_tvnow())) {
01689       /* Not within a sequence or not timed out. */
01690       return;
01691    }
01692 
01693    ast_bridge_channel_feature_digit(bridge_channel, 0);
01694 }

static void bridge_channel_handle_interval ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 1376 of file bridge_channel.c.

References ao2_ref, ast_atomic_fetchadd_int(), AST_BRIDGE_HOOK_TIMER_OPTION_MEDIA, ast_channel_name(), AST_CONTROL_SRCUPDATE, ast_debug, ast_heap_peek(), ast_heap_push(), ast_heap_remove(), ast_heap_unlock, ast_heap_wrlock, ast_indicate(), ast_samp2tv(), ast_test_flag, ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), bridge_channel_suspend(), bridge_channel_unsuspend(), ast_bridge_hook::callback, ast_bridge_channel::chan, ast_bridge_channel::features, ast_bridge_hook_timer::generic, ast_bridge_hook_timer_parms::heap_index, ast_bridge_hook::hook_pvt, ast_bridge_hook_timer_parms::interval, ast_bridge_features::interval_hooks, ast_bridge_features::interval_sequence, ast_bridge_hook_timer_parms::seqno, ast_bridge_hook_timer::timer, and ast_bridge_hook_timer_parms::trip_time.

Referenced by bridge_channel_wait().

01377 {
01378    struct ast_heap *interval_hooks;
01379    struct ast_bridge_hook_timer *hook;
01380    struct timeval start;
01381    int chan_suspended = 0;
01382 
01383    interval_hooks = bridge_channel->features->interval_hooks;
01384    ast_heap_wrlock(interval_hooks);
01385    start = ast_tvnow();
01386    while ((hook = ast_heap_peek(interval_hooks, 1))) {
01387       int interval;
01388       unsigned int execution_time;
01389 
01390       if (ast_tvdiff_ms(hook->timer.trip_time, start) > 0) {
01391          ast_debug(1, "Hook %p on %p(%s) wants to happen in the future, stopping our traversal\n",
01392             hook, bridge_channel, ast_channel_name(bridge_channel->chan));
01393          break;
01394       }
01395       ao2_ref(hook, +1);
01396       ast_heap_unlock(interval_hooks);
01397 
01398       if (!chan_suspended
01399          && ast_test_flag(&hook->timer, AST_BRIDGE_HOOK_TIMER_OPTION_MEDIA)) {
01400          chan_suspended = 1;
01401          bridge_channel_suspend(bridge_channel);
01402          ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01403       }
01404 
01405       ast_debug(1, "Executing hook %p on %p(%s)\n",
01406          hook, bridge_channel, ast_channel_name(bridge_channel->chan));
01407       interval = hook->generic.callback(bridge_channel, hook->generic.hook_pvt);
01408 
01409       ast_heap_wrlock(interval_hooks);
01410       if (ast_heap_peek(interval_hooks, hook->timer.heap_index) != hook
01411          || !ast_heap_remove(interval_hooks, hook)) {
01412          /* Interval hook is already removed from the bridge_channel. */
01413          ao2_ref(hook, -1);
01414          continue;
01415       }
01416       ao2_ref(hook, -1);
01417 
01418       if (interval < 0) {
01419          ast_debug(1, "Removed interval hook %p from %p(%s)\n",
01420             hook, bridge_channel, ast_channel_name(bridge_channel->chan));
01421          ao2_ref(hook, -1);
01422          continue;
01423       }
01424       if (interval) {
01425          /* Set new interval for the hook. */
01426          hook->timer.interval = interval;
01427       }
01428 
01429       ast_debug(1, "Updating interval hook %p with interval %u on %p(%s)\n",
01430          hook, hook->timer.interval, bridge_channel,
01431          ast_channel_name(bridge_channel->chan));
01432 
01433       /* resetting start */
01434       start = ast_tvnow();
01435 
01436       /*
01437        * Resetup the interval hook for the next interval.  We may need
01438        * to skip over any missed intervals because the hook was
01439        * delayed or took too long.
01440        */
01441       execution_time = ast_tvdiff_ms(start, hook->timer.trip_time);
01442       while (hook->timer.interval < execution_time) {
01443          execution_time -= hook->timer.interval;
01444       }
01445       hook->timer.trip_time = ast_tvadd(start, ast_samp2tv(hook->timer.interval - execution_time, 1000));
01446       hook->timer.seqno = ast_atomic_fetchadd_int((int *) &bridge_channel->features->interval_sequence, +1);
01447 
01448       if (ast_heap_push(interval_hooks, hook)) {
01449          /* Could not push the hook back onto the heap. */
01450          ao2_ref(hook, -1);
01451       }
01452    }
01453    ast_heap_unlock(interval_hooks);
01454 
01455    if (chan_suspended) {
01456       ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
01457       bridge_channel_unsuspend(bridge_channel);
01458    }
01459 }

static void bridge_channel_handle_write ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 2185 of file bridge_channel.c.

References ast_bridge_channel::activity, ast_assert, ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_channel_name(), AST_FRAME_BRIDGE_ACTION, AST_FRAME_BRIDGE_ACTION_SYNC, AST_FRAME_CONTROL, AST_FRAME_NULL, AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, ast_write(), bridge_channel_handle_action(), bridge_channel_handle_control(), bridge_channel_read_wr_queue_alert(), BRIDGE_CHANNEL_THREAD_SIMPLE, bridge_frame_free(), ast_bridge_channel::chan, ast_bridge_channel::collected, sync_payload::data, ast_frame::data, ast_bridge_channel::dtmf_hook_state, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, ast_frame::ptr, ast_frame::subclass, and ast_bridge_channel::wr_queue.

Referenced by bridge_channel_wait().

02186 {
02187    struct ast_frame *fr;
02188    struct sync_payload *sync_payload;
02189 
02190    ast_bridge_channel_lock(bridge_channel);
02191 
02192    /* It's not good to have unbalanced frames and alert_pipe alerts. */
02193    ast_assert(!AST_LIST_EMPTY(&bridge_channel->wr_queue));
02194    if (AST_LIST_EMPTY(&bridge_channel->wr_queue)) {
02195       /* No frame, flush the alert pipe of excess alerts. */
02196       ast_log(LOG_WARNING, "Weird.  No frame from bridge for %s to process?\n",
02197          ast_channel_name(bridge_channel->chan));
02198       bridge_channel_read_wr_queue_alert(bridge_channel);
02199       ast_bridge_channel_unlock(bridge_channel);
02200       return;
02201    }
02202 
02203    AST_LIST_TRAVERSE_SAFE_BEGIN(&bridge_channel->wr_queue, fr, frame_list) {
02204       if (bridge_channel->dtmf_hook_state.collected[0]) {
02205          switch (fr->frametype) {
02206          case AST_FRAME_BRIDGE_ACTION:
02207          case AST_FRAME_BRIDGE_ACTION_SYNC:
02208             /* Defer processing these frames while DTMF is collected. */
02209             continue;
02210          default:
02211             break;
02212          }
02213       }
02214       bridge_channel_read_wr_queue_alert(bridge_channel);
02215       AST_LIST_REMOVE_CURRENT(frame_list);
02216       break;
02217    }
02218    AST_LIST_TRAVERSE_SAFE_END;
02219 
02220    ast_bridge_channel_unlock(bridge_channel);
02221    if (!fr) {
02222       /*
02223        * Wait some to reduce CPU usage from a tight loop
02224        * without any wait because we only have deferred
02225        * frames in the wr_queue.
02226        */
02227       usleep(1);
02228       return;
02229    }
02230 
02231    switch (fr->frametype) {
02232    case AST_FRAME_BRIDGE_ACTION:
02233       bridge_channel_handle_action(bridge_channel, fr->subclass.integer, fr->data.ptr);
02234       break;
02235    case AST_FRAME_BRIDGE_ACTION_SYNC:
02236       sync_payload = fr->data.ptr;
02237       bridge_channel_handle_action(bridge_channel, fr->subclass.integer, sync_payload->data);
02238       break;
02239    case AST_FRAME_CONTROL:
02240       bridge_channel_handle_control(bridge_channel, fr);
02241       break;
02242    case AST_FRAME_NULL:
02243       break;
02244    default:
02245       /* Write the frame to the channel. */
02246       bridge_channel->activity = BRIDGE_CHANNEL_THREAD_SIMPLE;
02247       ast_write(bridge_channel->chan, fr);
02248       break;
02249    }
02250    bridge_frame_free(fr);
02251 }

struct ast_bridge_channel* bridge_channel_internal_alloc ( struct ast_bridge bridge  )  [read]

Definition at line 2819 of file bridge_channel.c.

References ast_bridge_channel::alert_pipe, ao2_alloc, ao2_ref, ast_cond_init, ast_bridge_channel::bridge, bridge_channel_destroy(), ast_bridge_channel::cond, NULL, and pipe_init_nonblock().

Referenced by ast_bridge_impart(), and ast_bridge_join().

02820 {
02821    struct ast_bridge_channel *bridge_channel;
02822 
02823    bridge_channel = ao2_alloc(sizeof(struct ast_bridge_channel), bridge_channel_destroy);
02824    if (!bridge_channel) {
02825       return NULL;
02826    }
02827    ast_cond_init(&bridge_channel->cond, NULL);
02828    if (pipe_init_nonblock(bridge_channel->alert_pipe)) {
02829       ao2_ref(bridge_channel, -1);
02830       return NULL;
02831    }
02832    if (bridge) {
02833       bridge_channel->bridge = bridge;
02834       ao2_ref(bridge_channel->bridge, +1);
02835    }
02836 
02837    return bridge_channel;
02838 }

int bridge_channel_internal_allows_optimization ( struct ast_bridge_channel bridge_channel  ) 

Definition at line 2730 of file bridge_channel.c.

References AST_LIST_EMPTY, ast_bridge_channel::in_bridge, and ast_bridge_channel::wr_queue.

Referenced by optimize_lock_chan_stack(), and optimize_lock_peer_stack().

02731 {
02732    return bridge_channel->in_bridge
02733       && AST_LIST_EMPTY(&bridge_channel->wr_queue);
02734 }

int bridge_channel_internal_join ( struct ast_bridge_channel bridge_channel  ) 

Definition at line 2543 of file bridge_channel.c.

References ao2_bump, ao2_t_cleanup, AST_BRIDGE_CAPABILITY_MULTIMIX, ast_bridge_channel_feature_digit(), ast_bridge_channel_kick(), ast_bridge_channel_lock_bridge(), ast_bridge_channel_restore_formats(), ast_bridge_features_merge(), ast_bridge_features_remove(), AST_BRIDGE_HOOK_REMOVE_ON_PULL, AST_BRIDGE_HOOK_TYPE_JOIN, AST_BRIDGE_HOOK_TYPE_LEAVE, ast_bridge_lock, ast_bridge_unlock, ast_channel_end_dtmf(), ast_channel_feature_hooks_get(), ast_channel_flags(), ast_channel_hold_state(), ast_channel_internal_bridge(), ast_channel_internal_bridge_set(), ast_channel_lock, ast_channel_name(), ast_channel_readformat(), ast_channel_sending_dtmf_digit(), ast_channel_sending_dtmf_tv(), ast_channel_unlock, ast_channel_writeformat(), AST_CONTROL_HOLD, AST_CONTROL_SRCCHANGE, AST_CONTROL_UNHOLD, ast_debug, AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT, AST_FLAG_ZOMBIE, ast_indicate(), ast_jb_enable_for_channel(), ast_read_threadstorage_callid(), ast_test_flag, ast_bridge_channel::bridge, bridge_channel_dissolve_check(), bridge_channel_event_join_leave(), bridge_channel_internal_pull(), bridge_channel_internal_push(), bridge_channel_settle_owed_events(), BRIDGE_CHANNEL_STATE_WAIT, bridge_channel_wait(), bridge_reconfigured(), ast_bridge::callid, ast_bridge_technology::capabilities, ast_bridge::cause, ast_bridge_channel::chan, ast_bridge_channel::features, ast_bridge_channel::inhibit_colp, NULL, ast_bridge_channel::read_format, ast_bridge_channel::state, ast_bridge_channel::swap, ast_bridge::technology, ast_bridge::uniqueid, and ast_bridge_channel::write_format.

Referenced by ast_bridge_join(), bridge_channel_depart_thread(), and bridge_channel_ind_thread().

02544 {
02545    int res = 0;
02546    struct ast_bridge_features *channel_features;
02547    struct ast_channel *swap;
02548 
02549    ast_debug(1, "Bridge %s: %p(%s) is joining\n",
02550       bridge_channel->bridge->uniqueid,
02551       bridge_channel, ast_channel_name(bridge_channel->chan));
02552 
02553    /*
02554     * Directly locking the bridge is safe here because nobody else
02555     * knows about this bridge_channel yet.
02556     */
02557    ast_bridge_lock(bridge_channel->bridge);
02558 
02559    ast_channel_lock(bridge_channel->chan);
02560 
02561    bridge_channel->read_format = ao2_bump(ast_channel_readformat(bridge_channel->chan));
02562    bridge_channel->write_format = ao2_bump(ast_channel_writeformat(bridge_channel->chan));
02563 
02564    /* Make sure we're still good to be put into a bridge */
02565    if (ast_channel_internal_bridge(bridge_channel->chan)
02566       || ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_ZOMBIE)) {
02567       ast_channel_unlock(bridge_channel->chan);
02568       ast_bridge_unlock(bridge_channel->bridge);
02569       ast_debug(1, "Bridge %s: %p(%s) failed to join Bridge\n",
02570          bridge_channel->bridge->uniqueid,
02571          bridge_channel,
02572          ast_channel_name(bridge_channel->chan));
02573       return -1;
02574    }
02575    ast_channel_internal_bridge_set(bridge_channel->chan, bridge_channel->bridge);
02576 
02577    /* Attach features requested by the channel */
02578    channel_features = ast_channel_feature_hooks_get(bridge_channel->chan);
02579    if (channel_features) {
02580       ast_bridge_features_merge(bridge_channel->features, channel_features);
02581    }
02582    ast_channel_unlock(bridge_channel->chan);
02583 
02584    /* Add the jitterbuffer if the channel requires it */
02585    ast_jb_enable_for_channel(bridge_channel->chan);
02586 
02587    if (!bridge_channel->bridge->callid) {
02588       bridge_channel->bridge->callid = ast_read_threadstorage_callid();
02589    }
02590 
02591    /* Take the swap channel ref from the bridge_channel struct. */
02592    swap = bridge_channel->swap;
02593 
02594    if (bridge_channel_internal_push(bridge_channel)) {
02595       int cause = bridge_channel->bridge->cause;
02596 
02597       ast_bridge_unlock(bridge_channel->bridge);
02598       ast_bridge_channel_kick(bridge_channel, cause);
02599       ast_bridge_channel_lock_bridge(bridge_channel);
02600       ast_bridge_features_remove(bridge_channel->features,
02601          AST_BRIDGE_HOOK_REMOVE_ON_PULL);
02602       bridge_channel_dissolve_check(bridge_channel);
02603       res = -1;
02604    }
02605    bridge_reconfigured(bridge_channel->bridge, !bridge_channel->inhibit_colp);
02606 
02607    if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
02608       /*
02609        * Indicate a source change since this channel is entering the
02610        * bridge system only if the bridge technology is not MULTIMIX
02611        * capable.  The MULTIMIX technology has already done it.
02612        */
02613       if (!(bridge_channel->bridge->technology->capabilities
02614          & AST_BRIDGE_CAPABILITY_MULTIMIX)) {
02615          ast_indicate(bridge_channel->chan, AST_CONTROL_SRCCHANGE);
02616       }
02617 
02618       ast_bridge_unlock(bridge_channel->bridge);
02619 
02620       /* Must release any swap ref after unlocking the bridge. */
02621       ao2_t_cleanup(swap, "Bridge push with swap successful");
02622       swap = NULL;
02623 
02624       bridge_channel_event_join_leave(bridge_channel, AST_BRIDGE_HOOK_TYPE_JOIN);
02625 
02626       while (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
02627          /* Wait for something to do. */
02628          bridge_channel_wait(bridge_channel);
02629       }
02630 
02631       /* Force a timeout on any accumulated DTMF hook digits. */
02632       ast_bridge_channel_feature_digit(bridge_channel, 0);
02633 
02634       bridge_channel_event_join_leave(bridge_channel, AST_BRIDGE_HOOK_TYPE_LEAVE);
02635       ast_bridge_channel_lock_bridge(bridge_channel);
02636    }
02637 
02638    bridge_channel_internal_pull(bridge_channel);
02639    bridge_channel_settle_owed_events(bridge_channel->bridge, bridge_channel);
02640    bridge_reconfigured(bridge_channel->bridge, 1);
02641 
02642    ast_bridge_unlock(bridge_channel->bridge);
02643 
02644    /* Must release any swap ref after unlocking the bridge. */
02645    ao2_t_cleanup(swap, "Bridge push with swap failed or exited immediately");
02646 
02647    /* Complete any active hold before exiting the bridge. */
02648    if (ast_channel_hold_state(bridge_channel->chan) == AST_CONTROL_HOLD) {
02649       ast_debug(1, "Channel %s simulating UNHOLD for bridge end.\n",
02650          ast_channel_name(bridge_channel->chan));
02651       ast_indicate(bridge_channel->chan, AST_CONTROL_UNHOLD);
02652    }
02653 
02654    /* Complete any partial DTMF digit before exiting the bridge. */
02655    if (ast_channel_sending_dtmf_digit(bridge_channel->chan)) {
02656       ast_channel_end_dtmf(bridge_channel->chan,
02657          ast_channel_sending_dtmf_digit(bridge_channel->chan),
02658          ast_channel_sending_dtmf_tv(bridge_channel->chan), "bridge end");
02659    }
02660 
02661    /* Indicate a source change since this channel is leaving the bridge system. */
02662    ast_indicate(bridge_channel->chan, AST_CONTROL_SRCCHANGE);
02663 
02664    /*
02665     * Wait for any dual redirect to complete.
02666     *
02667     * Must be done while "still in the bridge" for ast_async_goto()
02668     * to work right.
02669     */
02670    while (ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT)) {
02671       sched_yield();
02672    }
02673    ast_channel_lock(bridge_channel->chan);
02674    ast_channel_internal_bridge_set(bridge_channel->chan, NULL);
02675    ast_channel_unlock(bridge_channel->chan);
02676 
02677    ast_bridge_channel_restore_formats(bridge_channel);
02678 
02679    return res;
02680 }

void bridge_channel_internal_pull ( struct ast_bridge_channel bridge_channel  ) 

Definition at line 1952 of file bridge_channel.c.

References ast_bridge_channel_clear_roles(), AST_BRIDGE_CHANNEL_FLAG_LONELY, ast_bridge_publish_leave(), ast_channel_flags(), ast_channel_is_leaving_bridge(), ast_channel_name(), ast_clear_flag, ast_debug, AST_FLAG_OUTGOING, AST_LIST_REMOVE, ast_test_flag, ast_verb, ast_bridge_channel::bridge, bridge_channel_dissolve_check(), BRIDGE_CHANNEL_STATE_WAIT, ast_bridge_channel::chan, ast_bridge::channels, ast_bridge_features::feature_flags, ast_bridge_channel::features, ast_bridge_channel::in_bridge, ast_bridge_channel::just_joined, ast_bridge_technology::leave, ast_bridge_methods::name, ast_bridge_technology::name, ast_bridge::num_active, ast_bridge::num_channels, ast_bridge::num_lonely, ast_bridge_methods::pull, ast_bridge::reconfigured, ast_bridge_channel::state, ast_bridge_channel::suspended, ast_bridge::technology, ast_bridge::uniqueid, and ast_bridge::v_table.

Referenced by bridge_channel_internal_join(), bridge_channel_internal_push(), bridge_do_merge(), and bridge_do_move().

01953 {
01954    struct ast_bridge *bridge = bridge_channel->bridge;
01955 
01956    if (!bridge_channel->in_bridge) {
01957       return;
01958    }
01959    bridge_channel->in_bridge = 0;
01960 
01961    ast_debug(1, "Bridge %s: pulling %p(%s)\n",
01962       bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
01963 
01964    ast_verb(3, "Channel %s left '%s' %s-bridge <%s>\n",
01965       ast_channel_name(bridge_channel->chan),
01966       bridge->technology->name,
01967       bridge->v_table->name,
01968       bridge->uniqueid);
01969 
01970    if (!bridge_channel->just_joined) {
01971       /* Tell the bridge technology we are leaving so they tear us down */
01972       ast_debug(1, "Bridge %s: %p(%s) is leaving %s technology\n",
01973          bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
01974          bridge->technology->name);
01975       if (bridge->technology->leave) {
01976          bridge->technology->leave(bridge, bridge_channel);
01977       }
01978    }
01979 
01980    /* Remove channel from the bridge */
01981    if (!bridge_channel->suspended) {
01982       --bridge->num_active;
01983    }
01984    if (ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
01985       --bridge->num_lonely;
01986    }
01987    --bridge->num_channels;
01988    AST_LIST_REMOVE(&bridge->channels, bridge_channel, entry);
01989 
01990    bridge_channel_dissolve_check(bridge_channel);
01991    bridge->v_table->pull(bridge, bridge_channel);
01992 
01993    ast_bridge_channel_clear_roles(bridge_channel);
01994 
01995    /* If we are not going to be hung up after leaving a bridge, and we were an
01996     * outgoing channel, clear the outgoing flag.
01997     */
01998    if (ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_OUTGOING)
01999        && (ast_channel_is_leaving_bridge(bridge_channel->chan)
02000            || bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT)) {
02001       ast_debug(2, "Channel %s will survive this bridge; clearing outgoing (dialed) flag\n", ast_channel_name(bridge_channel->chan));
02002       ast_clear_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_OUTGOING);
02003    }
02004 
02005    bridge->reconfigured = 1;
02006    ast_bridge_publish_leave(bridge, bridge_channel->chan);
02007 }

int bridge_channel_internal_push ( struct ast_bridge_channel bridge_channel  ) 

Definition at line 2009 of file bridge_channel.c.

References ast_assert, ast_bridge_channel_establish_roles(), AST_BRIDGE_CHANNEL_FLAG_LONELY, ast_bridge_channel_leave_bridge(), AST_BRIDGE_FLAG_DISSOLVE_EMPTY, ast_bridge_publish_enter(), ast_channel_name(), ast_clear_flag, ast_debug, AST_LIST_INSERT_TAIL, ast_null_frame, ast_queue_frame(), ast_set2_flag, ast_test_flag, ast_verb, ast_bridge_channel::bridge, bridge_channel_internal_pull(), BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, BRIDGE_CHANNEL_STATE_WAIT, bridge_find_channel(), ast_bridge_channel::chan, ast_bridge::channels, ast_bridge::dissolved, ast_bridge_features::feature_flags, ast_bridge::feature_flags, ast_bridge_channel::features, ast_bridge_channel::in_bridge, ast_bridge_channel::just_joined, ast_bridge_methods::name, ast_bridge_technology::name, NULL, ast_bridge::num_active, ast_bridge::num_channels, ast_bridge::num_lonely, pbx_builtin_setvar_helper(), ast_bridge_methods::push, ast_bridge::reconfigured, ast_bridge_channel::state, ast_bridge_channel::suspended, ast_bridge_channel::swap, ast_bridge::technology, ast_bridge::uniqueid, and ast_bridge::v_table.

Referenced by bridge_channel_internal_join(), bridge_do_merge(), and bridge_do_move().

02010 {
02011    struct ast_bridge *bridge = bridge_channel->bridge;
02012    struct ast_bridge_channel *swap;
02013 
02014    ast_assert(!bridge_channel->in_bridge);
02015 
02016    swap = bridge_find_channel(bridge, bridge_channel->swap);
02017    bridge_channel->swap = NULL;
02018 
02019    if (swap) {
02020       ast_debug(1, "Bridge %s: pushing %p(%s) by swapping with %p(%s)\n",
02021          bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
02022          swap, ast_channel_name(swap->chan));
02023    } else {
02024       ast_debug(1, "Bridge %s: pushing %p(%s)\n",
02025          bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
02026    }
02027 
02028    /* Add channel to the bridge */
02029    if (bridge->dissolved
02030       || bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT
02031       || (swap && swap->state != BRIDGE_CHANNEL_STATE_WAIT)
02032       || bridge->v_table->push(bridge, bridge_channel, swap)
02033       || ast_bridge_channel_establish_roles(bridge_channel)) {
02034       ast_debug(1, "Bridge %s: pushing %p(%s) into bridge failed\n",
02035          bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
02036       return -1;
02037    }
02038 
02039    if (swap) {
02040       int dissolve = ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_EMPTY);
02041 
02042       /* This flag is cleared so the act of this channel leaving does not cause it to dissolve if need be */
02043       ast_clear_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_EMPTY);
02044 
02045       ast_bridge_channel_leave_bridge(swap, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, 0);
02046       bridge_channel_internal_pull(swap);
02047 
02048       ast_set2_flag(&bridge->feature_flags, dissolve, AST_BRIDGE_FLAG_DISSOLVE_EMPTY);
02049    }
02050 
02051    bridge_channel->in_bridge = 1;
02052    bridge_channel->just_joined = 1;
02053    AST_LIST_INSERT_TAIL(&bridge->channels, bridge_channel, entry);
02054    ++bridge->num_channels;
02055    if (ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
02056       ++bridge->num_lonely;
02057    }
02058    if (!bridge_channel->suspended) {
02059       ++bridge->num_active;
02060    }
02061 
02062    ast_verb(3, "Channel %s %s%s%s '%s' %s-bridge <%s>\n",
02063       ast_channel_name(bridge_channel->chan),
02064       swap ? "swapped with " : "joined",
02065       swap ? ast_channel_name(swap->chan) : "",
02066       swap ? " into" : "",
02067       bridge->technology->name,
02068       bridge->v_table->name,
02069       bridge->uniqueid);
02070 
02071    ast_bridge_publish_enter(bridge, bridge_channel->chan, swap ? swap->chan : NULL);
02072 
02073    /* Clear any BLINDTRANSFER and ATTENDEDTRANSFER since the transfer has completed. */
02074    pbx_builtin_setvar_helper(bridge_channel->chan, "BLINDTRANSFER", NULL);
02075    pbx_builtin_setvar_helper(bridge_channel->chan, "ATTENDEDTRANSFER", NULL);
02076 
02077    /* Wake up the bridge channel thread to reevaluate any interval timers. */
02078    ast_queue_frame(bridge_channel->chan, &ast_null_frame);
02079 
02080    bridge->reconfigured = 1;
02081    return 0;
02082 }

int bridge_channel_internal_queue_attended_transfer ( struct ast_channel transferee,
struct ast_channel unbridged_chan 
)

Definition at line 2708 of file bridge_channel.c.

References ao2_cleanup, ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_name(), AST_CHANNEL_NAME, ast_channel_unlock, ast_copy_string(), BRIDGE_CHANNEL_ACTION_ATTENDED_TRANSFER, bridge_channel_queue_action_data(), NULL, and RAII_VAR.

Referenced by ast_bridge_transfer_attended().

02710 {
02711    RAII_VAR(struct ast_bridge_channel *, transferee_bridge_channel, NULL, ao2_cleanup);
02712    char unbridged_chan_name[AST_CHANNEL_NAME];
02713 
02714    ast_channel_lock(transferee);
02715    transferee_bridge_channel = ast_channel_get_bridge_channel(transferee);
02716    ast_channel_unlock(transferee);
02717 
02718    if (!transferee_bridge_channel) {
02719       return -1;
02720    }
02721 
02722    ast_copy_string(unbridged_chan_name, ast_channel_name(unbridged_chan),
02723       sizeof(unbridged_chan_name));
02724 
02725    return bridge_channel_queue_action_data(transferee_bridge_channel,
02726       BRIDGE_CHANNEL_ACTION_ATTENDED_TRANSFER, unbridged_chan_name,
02727       sizeof(unbridged_chan_name));
02728 }

int bridge_channel_internal_queue_blind_transfer ( struct ast_channel transferee,
const char *  exten,
const char *  context,
transfer_channel_cb  new_channel_cb,
void *  user_data 
)

Definition at line 2682 of file bridge_channel.c.

References ao2_cleanup, AST_BRIDGE_TRANSFER_SINGLE_PARTY, ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), BRIDGE_CHANNEL_ACTION_BLIND_TRANSFER, bridge_channel_queue_action_data(), blind_transfer_data::context, blind_transfer_data::exten, NULL, and RAII_VAR.

Referenced by ast_bridge_transfer_blind().

02685 {
02686    RAII_VAR(struct ast_bridge_channel *, transferee_bridge_channel, NULL, ao2_cleanup);
02687    struct blind_transfer_data blind_data;
02688 
02689    ast_channel_lock(transferee);
02690    transferee_bridge_channel = ast_channel_get_bridge_channel(transferee);
02691    ast_channel_unlock(transferee);
02692 
02693    if (!transferee_bridge_channel) {
02694       return -1;
02695    }
02696 
02697    if (new_channel_cb) {
02698       new_channel_cb(transferee, user_data, AST_BRIDGE_TRANSFER_SINGLE_PARTY);
02699    }
02700 
02701    ast_copy_string(blind_data.exten, exten, sizeof(blind_data.exten));
02702    ast_copy_string(blind_data.context, context, sizeof(blind_data.context));
02703 
02704    return bridge_channel_queue_action_data(transferee_bridge_channel,
02705       BRIDGE_CHANNEL_ACTION_BLIND_TRANSFER, &blind_data, sizeof(blind_data));
02706 }

void bridge_channel_internal_suspend_nolock ( struct ast_bridge_channel bridge_channel  ) 

Definition at line 705 of file bridge_channel.c.

References ast_bridge_channel::bridge, ast_bridge_channel::in_bridge, ast_bridge::num_active, ast_bridge_technology::suspend, ast_bridge_channel::suspended, and ast_bridge::technology.

Referenced by ast_bridge_channel_feature_digit(), ast_bridge_suspend(), and bridge_channel_suspend().

00706 {
00707    bridge_channel->suspended = 1;
00708    if (bridge_channel->in_bridge) {
00709       --bridge_channel->bridge->num_active;
00710    }
00711 
00712    /* Get technology bridge threads off of the channel. */
00713    if (bridge_channel->bridge->technology->suspend) {
00714       bridge_channel->bridge->technology->suspend(bridge_channel->bridge, bridge_channel);
00715    }
00716 }

void bridge_channel_internal_unsuspend_nolock ( struct ast_bridge_channel bridge_channel  ) 

Definition at line 743 of file bridge_channel.c.

References ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_cond_signal, ast_bridge_channel::bridge, ast_bridge_channel::cond, ast_bridge_channel::in_bridge, ast_bridge::num_active, ast_bridge_channel::suspended, ast_bridge::technology, and ast_bridge_technology::unsuspend.

Referenced by ast_bridge_unsuspend(), and bridge_channel_unsuspend().

00744 {
00745    bridge_channel->suspended = 0;
00746    if (bridge_channel->in_bridge) {
00747       ++bridge_channel->bridge->num_active;
00748    }
00749 
00750    /* Wake technology bridge threads to take care of channel again. */
00751    if (bridge_channel->bridge->technology->unsuspend) {
00752       bridge_channel->bridge->technology->unsuspend(bridge_channel->bridge, bridge_channel);
00753    }
00754 
00755    /* Wake suspended channel. */
00756    ast_bridge_channel_lock(bridge_channel);
00757    ast_cond_signal(&bridge_channel->cond);
00758    ast_bridge_channel_unlock(bridge_channel);
00759 }

static int bridge_channel_next_interval ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 2361 of file bridge_channel.c.

References ast_heap_peek(), ast_heap_unlock, ast_heap_wrlock, ast_tvdiff_ms(), ast_tvnow(), ast_bridge_channel::features, ast_bridge_features::interval_hooks, ast_bridge_hook_timer::timer, and ast_bridge_hook_timer_parms::trip_time.

Referenced by bridge_channel_next_timeout().

02362 {
02363    struct ast_heap *interval_hooks = bridge_channel->features->interval_hooks;
02364    struct ast_bridge_hook_timer *hook;
02365    int ms;
02366 
02367    ast_heap_wrlock(interval_hooks);
02368    hook = ast_heap_peek(interval_hooks, 1);
02369    if (hook) {
02370       ms = ast_tvdiff_ms(hook->timer.trip_time, ast_tvnow());
02371       if (ms < 0) {
02372          /* Expire immediately.  An interval hook is ready to run. */
02373          ms = 0;
02374       }
02375    } else {
02376       /* No hook so wait forever. */
02377       ms = -1;
02378    }
02379    ast_heap_unlock(interval_hooks);
02380 
02381    return ms;
02382 }

static int bridge_channel_next_timeout ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 2423 of file bridge_channel.c.

References bridge_channel_feature_timeout(), and bridge_channel_next_interval().

Referenced by bridge_channel_wait().

02424 {
02425    int ms_interval;
02426    int ms;
02427 
02428    ms_interval = bridge_channel_next_interval(bridge_channel);
02429    ms = bridge_channel_feature_timeout(bridge_channel);
02430    if (ms < 0 || (0 <= ms_interval && ms_interval < ms)) {
02431       /* Interval hook timeout is next. */
02432       ms = ms_interval;
02433    }
02434 
02435    return ms;
02436 }

static void bridge_channel_park ( struct ast_bridge_channel bridge_channel,
struct bridge_park payload 
) [static]

Definition at line 1317 of file bridge_channel.c.

References bridge_park::app_data_offset, ast_channel_name(), ast_log, AST_LOG_WARNING, ast_parking_park_bridge_channel(), ast_parking_provider_registered(), ast_bridge_channel::chan, NULL, bridge_park::parkee_uuid, and bridge_park::parker_uuid_offset.

Referenced by bridge_channel_handle_action().

01318 {
01319    if (!ast_parking_provider_registered()) {
01320       ast_log(AST_LOG_WARNING, "Unable to park %s: No parking provider loaded!\n",
01321          ast_channel_name(bridge_channel->chan));
01322       return;
01323    }
01324 
01325    if (ast_parking_park_bridge_channel(bridge_channel, payload->parkee_uuid,
01326       &payload->parkee_uuid[payload->parker_uuid_offset],
01327       payload->app_data_offset ? &payload->parkee_uuid[payload->app_data_offset] : NULL)) {
01328       ast_log(AST_LOG_WARNING, "Error occurred while parking %s\n",
01329          ast_channel_name(bridge_channel->chan));
01330    }
01331 }

static void bridge_channel_playfile ( struct ast_bridge_channel bridge_channel,
struct bridge_playfile payload 
) [static]

Definition at line 1174 of file bridge_channel.c.

References ast_bridge_channel_playfile(), bridge_playfile::custom_play, bridge_playfile::moh_offset, NULL, and bridge_playfile::playfile.

Referenced by bridge_channel_handle_action().

01175 {
01176    ast_bridge_channel_playfile(bridge_channel, payload->custom_play, payload->playfile,
01177       payload->moh_offset ? &payload->playfile[payload->moh_offset] : NULL);
01178 }

static void bridge_channel_poke ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 247 of file bridge_channel.c.

References ast_null_frame, ast_queue_frame(), ast_bridge_channel::chan, and ast_bridge_channel::thread.

Referenced by ast_bridge_channel_leave_bridge_nolock().

00248 {
00249    if (!pthread_equal(pthread_self(), bridge_channel->thread)) {
00250       /* Wake up the bridge channel thread. */
00251       ast_queue_frame(bridge_channel->chan, &ast_null_frame);
00252    }
00253 }

static int bridge_channel_queue_action_data ( struct ast_bridge_channel bridge_channel,
enum bridge_channel_action_type  action,
const void *  data,
size_t  datalen 
) [static]

Definition at line 789 of file bridge_channel.c.

References ast_bridge_channel_queue_frame(), AST_FRAME_BRIDGE_ACTION, and ast_frame::frametype.

Referenced by ast_bridge_channel_queue_app(), ast_bridge_channel_queue_callback(), ast_bridge_channel_queue_playfile(), bridge_channel_internal_queue_attended_transfer(), and bridge_channel_internal_queue_blind_transfer().

00791 {
00792    struct ast_frame frame = {
00793       .frametype = AST_FRAME_BRIDGE_ACTION,
00794       .subclass.integer = action,
00795       .datalen = datalen,
00796       .data.ptr = (void *) data,
00797    };
00798 
00799    return ast_bridge_channel_queue_frame(bridge_channel, &frame);
00800 }

static int bridge_channel_queue_action_data_sync ( struct ast_bridge_channel bridge_channel,
enum bridge_channel_action_type  action,
const void *  data,
size_t  datalen 
) [static]

Definition at line 817 of file bridge_channel.c.

References ast_alloca, ast_assert, ast_atomic_fetchadd_int(), ast_bridge_channel_queue_frame(), AST_FRAME_BRIDGE_ACTION_SYNC, bridge_sync_cleanup(), bridge_sync_init(), bridge_sync_wait(), ast_frame::data, sync_payload::data, ast_frame::datalen, ast_frame::frametype, sync_payload::id, ast_frame::ptr, and ast_bridge_channel::thread.

Referenced by ast_bridge_channel_queue_playfile_sync().

00819 {
00820    struct sync_payload *sync_payload;
00821    int sync_payload_len = sizeof(*sync_payload) + datalen;
00822    struct bridge_sync sync_struct;
00823    struct ast_frame frame = {
00824       .frametype = AST_FRAME_BRIDGE_ACTION_SYNC,
00825       .subclass.integer = action,
00826    };
00827 
00828    /* Make sure we don't end up trying to wait on ourself to deliver the frame */
00829    ast_assert(!pthread_equal(pthread_self(), bridge_channel->thread));
00830 
00831    sync_payload = ast_alloca(sync_payload_len);
00832    sync_payload->id = ast_atomic_fetchadd_int(&sync_ids, +1);
00833    memcpy(sync_payload->data, data, datalen);
00834 
00835    frame.datalen = sync_payload_len;
00836    frame.data.ptr = sync_payload;
00837 
00838    bridge_sync_init(&sync_struct, sync_payload->id);
00839    if (ast_bridge_channel_queue_frame(bridge_channel, &frame)) {
00840       bridge_sync_cleanup(&sync_struct);
00841       return -1;
00842    }
00843 
00844    bridge_sync_wait(&sync_struct);
00845    bridge_sync_cleanup(&sync_struct);
00846    return 0;
00847 }

static void bridge_channel_read_wr_queue_alert ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 2163 of file bridge_channel.c.

References ast_bridge_channel::alert_pipe, ast_channel_name(), ast_log, ast_bridge_channel::chan, errno, and LOG_WARNING.

Referenced by bridge_channel_handle_write().

02164 {
02165    char nudge;
02166 
02167    if (read(bridge_channel->alert_pipe[0], &nudge, sizeof(nudge)) < 0) {
02168       if (errno != EINTR && errno != EAGAIN) {
02169          ast_log(LOG_WARNING, "read() failed for alert pipe on %p(%s): %s\n",
02170             bridge_channel, ast_channel_name(bridge_channel->chan),
02171             strerror(errno));
02172       }
02173    }
02174 }

static void bridge_channel_run_app ( struct ast_bridge_channel bridge_channel,
struct bridge_run_app data 
) [static]

Definition at line 1080 of file bridge_channel.c.

References bridge_run_app::app_args_offset, bridge_run_app::app_name, ast_bridge_channel_run_app(), bridge_run_app::moh_offset, and NULL.

Referenced by bridge_channel_handle_action().

01081 {
01082    ast_bridge_channel_run_app(bridge_channel, data->app_name,
01083       data->app_args_offset ? &data->app_name[data->app_args_offset] : NULL,
01084       data->moh_offset ? &data->app_name[data->moh_offset] : NULL);
01085 }

void bridge_channel_settle_owed_events ( struct ast_bridge orig_bridge,
struct ast_bridge_channel bridge_channel 
)

Definition at line 674 of file bridge_channel.c.

References ast_channel_name(), AST_FRAME_DTMF_END, ast_log, ast_tvdiff_ms(), ast_tvnow(), ast_bridge_channel::chan, ast_bridge_channel::dtmf_digit, ast_bridge_channel::dtmf_tv, ast_frame::frametype, ast_frame::len, LOG_DTMF, NULL, option_dtmfminduration, ast_bridge_channel::owed, ast_bridge::technology, ast_bridge::uniqueid, and ast_bridge_technology::write.

Referenced by bridge_channel_internal_join(), and bridge_do_move().

00675 {
00676    if (bridge_channel->owed.dtmf_digit) {
00677       struct ast_frame frame = {
00678          .frametype = AST_FRAME_DTMF_END,
00679          .subclass.integer = bridge_channel->owed.dtmf_digit,
00680          .src = "Bridge channel owed DTMF",
00681       };
00682 
00683       frame.len = ast_tvdiff_ms(ast_tvnow(), bridge_channel->owed.dtmf_tv);
00684       if (frame.len < option_dtmfminduration) {
00685          frame.len = option_dtmfminduration;
00686       }
00687       ast_log(LOG_DTMF, "DTMF end '%c' simulated to bridge %s because %s left.  Duration %ld ms.\n",
00688          bridge_channel->owed.dtmf_digit, orig_bridge->uniqueid,
00689          ast_channel_name(bridge_channel->chan), frame.len);
00690       bridge_channel->owed.dtmf_digit = '\0';
00691       orig_bridge->technology->write(orig_bridge, NULL, &frame);
00692    }
00693 }

static void bridge_channel_suspend ( struct ast_bridge_channel bridge_channel  )  [static]

static void bridge_channel_talking ( struct ast_bridge_channel bridge_channel,
int  talking 
) [static]

Definition at line 1700 of file bridge_channel.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ao2_unlink, AST_BRIDGE_HOOK_TYPE_TALK, ast_channel_name(), ast_debug, ast_bridge_hook::callback, ast_bridge_channel::chan, ast_bridge_channel::features, ast_bridge_hook::hook_pvt, ast_bridge_features::other_hooks, and ast_bridge_hook::type.

Referenced by bridge_channel_handle_action().

01701 {
01702    struct ast_bridge_features *features = bridge_channel->features;
01703    struct ast_bridge_hook *hook;
01704    struct ao2_iterator iter;
01705 
01706    /* Run any talk detection hooks. */
01707    iter = ao2_iterator_init(features->other_hooks, 0);
01708    for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
01709       int remove_me;
01710       ast_bridge_talking_indicate_callback talk_cb;
01711 
01712       if (hook->type != AST_BRIDGE_HOOK_TYPE_TALK) {
01713          continue;
01714       }
01715       talk_cb = (ast_bridge_talking_indicate_callback) hook->callback;
01716       remove_me = talk_cb(bridge_channel, hook->hook_pvt, talking);
01717       if (remove_me) {
01718          ast_debug(1, "Talk detection hook %p is being removed from %p(%s)\n",
01719             hook, bridge_channel, ast_channel_name(bridge_channel->chan));
01720          ao2_unlink(features->other_hooks, hook);
01721       }
01722    }
01723    ao2_iterator_destroy(&iter);
01724 }

static void bridge_channel_unsuspend ( struct ast_bridge_channel bridge_channel  )  [static]

static void bridge_channel_update_accountcodes_joining ( struct ast_bridge_channel joining,
struct ast_bridge_channel swap 
) [static]

Definition at line 513 of file bridge_channel.c.

References ast_assert, ast_channel_lock_both, ast_channel_unlock, AST_LIST_TRAVERSE, ast_bridge_channel::bridge, ast_bridge_channel::chan, channel_set_empty_accountcodes(), channel_update_peeraccounts(), ast_bridge::channels, and ast_bridge::num_channels.

Referenced by ast_bridge_channel_update_accountcodes().

00514 {
00515    struct ast_bridge *bridge = joining->bridge;
00516    struct ast_bridge_channel *other;
00517    unsigned int swap_in_bridge = 0;
00518    unsigned int will_be_two_party;
00519 
00520    /*
00521     * Only update the peeraccount to match if the joining channel
00522     * will make it a two party bridge.
00523     */
00524    if (bridge->num_channels <= 2 && swap) {
00525       AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
00526          if (other == swap) {
00527             swap_in_bridge = 1;
00528             break;
00529          }
00530       }
00531    }
00532    will_be_two_party = (1 == bridge->num_channels - swap_in_bridge);
00533 
00534    AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
00535       if (other == swap) {
00536          continue;
00537       }
00538       ast_assert(joining != other);
00539       ast_channel_lock_both(joining->chan, other->chan);
00540       channel_set_empty_accountcodes(joining->chan, other->chan);
00541       if (will_be_two_party) {
00542          channel_update_peeraccounts(joining->chan, other->chan);
00543       }
00544       ast_channel_unlock(joining->chan);
00545       ast_channel_unlock(other->chan);
00546    }
00547 }

static void bridge_channel_update_accountcodes_leaving ( struct ast_bridge_channel leaving  )  [static]

Definition at line 560 of file bridge_channel.c.

References ast_assert, ast_channel_lock_both, ast_channel_unlock, AST_LIST_FIRST, AST_LIST_LAST, ast_bridge_channel::bridge, ast_bridge_channel::chan, channel_set_empty_accountcodes(), channel_update_peeraccounts(), ast_bridge::channels, ast_bridge::dissolved, first, and ast_bridge::num_channels.

Referenced by ast_bridge_channel_update_accountcodes().

00561 {
00562    struct ast_bridge *bridge = leaving->bridge;
00563    struct ast_bridge_channel *first;
00564    struct ast_bridge_channel *second;
00565 
00566    if (bridge->num_channels != 2 || bridge->dissolved) {
00567       return;
00568    }
00569 
00570    first = AST_LIST_FIRST(&bridge->channels);
00571    second = AST_LIST_LAST(&bridge->channels);
00572    ast_assert(first && first != second);
00573    ast_channel_lock_both(first->chan, second->chan);
00574    channel_set_empty_accountcodes(first->chan, second->chan);
00575    channel_update_peeraccounts(first->chan, second->chan);
00576    ast_channel_unlock(second->chan);
00577    ast_channel_unlock(first->chan);
00578 }

static void bridge_channel_wait ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 2449 of file bridge_channel.c.

References ast_bridge_channel::activity, ast_bridge_channel::alert_pipe, ao2_object_get_lockaddr(), ast_bridge_channel_lock, ast_bridge_channel_lock_bridge(), ast_bridge_channel_unlock, ast_bridge_unlock, ast_channel_name(), ast_channel_set_unbridged(), ast_channel_unbridged(), ast_cond_wait, ast_debug, ast_waitfor_nandfds(), ast_bridge_channel::bridge, bridge_channel_handle_feature_timeout(), bridge_channel_handle_interval(), bridge_channel_handle_write(), bridge_channel_next_timeout(), BRIDGE_CHANNEL_STATE_WAIT, BRIDGE_CHANNEL_THREAD_FRAME, BRIDGE_CHANNEL_THREAD_IDLE, bridge_handle_trip(), bridge_reconfigured(), ast_bridge_channel::chan, ast_bridge_channel::cond, NULL, ast_bridge::reconfigured, ast_bridge_channel::state, ast_bridge_channel::suspended, and ast_bridge::uniqueid.

Referenced by bridge_channel_internal_join().

02450 {
02451    int ms;
02452    int outfd;
02453    struct ast_channel *chan;
02454 
02455    /* Wait for data to either come from the channel or us to be signaled */
02456    ast_bridge_channel_lock(bridge_channel);
02457    if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
02458    } else if (bridge_channel->suspended) {
02459 /* XXX ASTERISK-21271 the external party use of suspended will go away as will these references because this is the bridge channel thread */
02460       ast_debug(1, "Bridge %s: %p(%s) is going into a signal wait\n",
02461          bridge_channel->bridge->uniqueid, bridge_channel,
02462          ast_channel_name(bridge_channel->chan));
02463       ast_cond_wait(&bridge_channel->cond, ao2_object_get_lockaddr(bridge_channel));
02464    } else {
02465       ast_bridge_channel_unlock(bridge_channel);
02466       outfd = -1;
02467       ms = bridge_channel_next_timeout(bridge_channel);
02468       chan = ast_waitfor_nandfds(&bridge_channel->chan, 1,
02469          &bridge_channel->alert_pipe[0], 1, NULL, &outfd, &ms);
02470       if (ast_channel_unbridged(bridge_channel->chan)) {
02471          ast_channel_set_unbridged(bridge_channel->chan, 0);
02472          ast_bridge_channel_lock_bridge(bridge_channel);
02473          bridge_channel->bridge->reconfigured = 1;
02474          bridge_reconfigured(bridge_channel->bridge, 0);
02475          ast_bridge_unlock(bridge_channel->bridge);
02476       }
02477       ast_bridge_channel_lock(bridge_channel);
02478       bridge_channel->activity = BRIDGE_CHANNEL_THREAD_FRAME;
02479       ast_bridge_channel_unlock(bridge_channel);
02480       if (!bridge_channel->suspended
02481          && bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
02482          if (chan) {
02483             bridge_handle_trip(bridge_channel);
02484          } else if (ms == 0) {
02485             /* An interdigit timeout or interval expired. */
02486             bridge_channel_handle_feature_timeout(bridge_channel);
02487             bridge_channel_handle_interval(bridge_channel);
02488          } else if (-1 < outfd) {
02489             /*
02490              * Must do this after checking timeouts or may have
02491              * an infinite loop due to deferring write queue
02492              * actions while trying to match DTMF feature hooks.
02493              */
02494             bridge_channel_handle_write(bridge_channel);
02495          }
02496       }
02497       bridge_channel->activity = BRIDGE_CHANNEL_THREAD_IDLE;
02498       return;
02499    }
02500    ast_bridge_channel_unlock(bridge_channel);
02501 }

static int bridge_channel_write_action_data ( struct ast_bridge_channel bridge_channel,
enum bridge_channel_action_type  action,
const void *  data,
size_t  datalen 
) [static]

Definition at line 861 of file bridge_channel.c.

References AST_FRAME_BRIDGE_ACTION, bridge_channel_write_frame(), and ast_frame::frametype.

Referenced by ast_bridge_channel_write_app(), ast_bridge_channel_write_callback(), ast_bridge_channel_write_park(), ast_bridge_channel_write_playfile(), and bridge_channel_write_dtmf_stream().

00863 {
00864    struct ast_frame frame = {
00865       .frametype = AST_FRAME_BRIDGE_ACTION,
00866       .subclass.integer = action,
00867       .datalen = datalen,
00868       .data.ptr = (void *) data,
00869    };
00870 
00871    return bridge_channel_write_frame(bridge_channel, &frame);
00872 }

static int bridge_channel_write_dtmf_stream ( struct ast_bridge_channel bridge_channel,
const char *  dtmf 
) [static]

Definition at line 1465 of file bridge_channel.c.

References BRIDGE_CHANNEL_ACTION_DTMF_STREAM, and bridge_channel_write_action_data().

Referenced by ast_bridge_channel_feature_digit().

01466 {
01467    return bridge_channel_write_action_data(bridge_channel,
01468       BRIDGE_CHANNEL_ACTION_DTMF_STREAM, dtmf, strlen(dtmf) + 1);
01469 }

static int bridge_channel_write_frame ( struct ast_bridge_channel bridge_channel,
struct ast_frame frame 
) [static]

Definition at line 634 of file bridge_channel.c.

References ast_assert, ast_bridge_channel_lock_bridge(), ast_bridge_unlock, AST_FRAME_BRIDGE_ACTION_SYNC, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_tvnow(), ast_bridge_channel::bridge, ast_bridge_channel::dtmf_digit, ast_bridge_channel::dtmf_tv, ast_frame::frametype, ast_frame_subclass::integer, ast_bridge_channel::owed, ast_frame::subclass, ast_bridge::technology, and ast_bridge_technology::write.

Referenced by ast_bridge_channel_write_control_data(), bridge_channel_write_action_data(), and bridge_handle_trip().

00635 {
00636    ast_assert(frame->frametype != AST_FRAME_BRIDGE_ACTION_SYNC);
00637 
00638    ast_bridge_channel_lock_bridge(bridge_channel);
00639 /*
00640  * XXX need to implement a deferred write queue for when there
00641  * is no peer channel in the bridge (yet or it was kicked).
00642  *
00643  * The tech decides if a frame needs to be pushed back for deferral.
00644  * simple_bridge/native_bridge are likely the only techs that will do this.
00645  */
00646    bridge_channel->bridge->technology->write(bridge_channel->bridge, bridge_channel, frame);
00647 
00648    /* Remember any owed events to the bridge. */
00649    switch (frame->frametype) {
00650    case AST_FRAME_DTMF_BEGIN:
00651       bridge_channel->owed.dtmf_tv = ast_tvnow();
00652       bridge_channel->owed.dtmf_digit = frame->subclass.integer;
00653       break;
00654    case AST_FRAME_DTMF_END:
00655       bridge_channel->owed.dtmf_digit = '\0';
00656       break;
00657    case AST_FRAME_CONTROL:
00658       /*
00659        * We explicitly will not remember HOLD/UNHOLD frames because
00660        * things like attended transfers will handle them.
00661        */
00662    default:
00663       break;
00664    }
00665    ast_bridge_unlock(bridge_channel->bridge);
00666 
00667    /*
00668     * Claim successful write to bridge.  If deferred frame
00669     * support is added, claim successfully deferred.
00670     */
00671    return 0;
00672 }

static void bridge_frame_free ( struct ast_frame frame  )  [static]

Definition at line 874 of file bridge_channel.c.

References AST_FRAME_BRIDGE_ACTION_SYNC, ast_frfree, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, bridge_sync_signal(), ast_frame::data, ast_frame::frametype, sync_payload::id, bridge_sync::id, bridge_sync::list, and ast_frame::ptr.

Referenced by ast_bridge_channel_queue_frame(), bridge_channel_destroy(), bridge_channel_handle_write(), bridge_handle_dtmf(), and bridge_handle_trip().

00875 {
00876    if (frame->frametype == AST_FRAME_BRIDGE_ACTION_SYNC) {
00877       struct sync_payload *sync_payload = frame->data.ptr;
00878       struct bridge_sync *sync;
00879 
00880       AST_RWLIST_RDLOCK(&sync_structs);
00881       AST_RWLIST_TRAVERSE(&sync_structs, sync, list) {
00882          if (sync->id == sync_payload->id) {
00883             break;
00884          }
00885       }
00886       if (sync) {
00887          bridge_sync_signal(sync);
00888       }
00889       AST_RWLIST_UNLOCK(&sync_structs);
00890    }
00891 
00892    ast_frfree(frame);
00893 }

static struct ast_frame* bridge_handle_dtmf ( struct ast_bridge_channel bridge_channel,
struct ast_frame frame 
) [static, read]

Internal function to handle DTMF from a channel.

Definition at line 2254 of file bridge_channel.c.

References ao2_cleanup, ao2_find, ast_assert, ast_bridge_channel_feature_digit(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_test_suite_event_notify, bridge_frame_free(), ast_bridge_channel::collected, ast_bridge_hook_dtmf::dtmf, ast_bridge_channel::dtmf_hook_state, ast_bridge_features::dtmf_hooks, ast_bridge_channel::features, ast_frame::frametype, ast_frame_subclass::integer, NULL, OBJ_SEARCH_PARTIAL_KEY, and ast_frame::subclass.

Referenced by bridge_handle_trip().

02255 {
02256    struct ast_bridge_features *features = bridge_channel->features;
02257    struct ast_bridge_hook_dtmf *hook = NULL;
02258    char dtmf[2];
02259 
02260    /*
02261     * See if we are already matching a DTMF feature hook sequence or
02262     * if this DTMF matches the beginning of any DTMF feature hooks.
02263     */
02264    dtmf[0] = frame->subclass.integer;
02265    dtmf[1] = '\0';
02266    if (bridge_channel->dtmf_hook_state.collected[0]
02267       || (hook = ao2_find(features->dtmf_hooks, dtmf, OBJ_SEARCH_PARTIAL_KEY))) {
02268       enum ast_frame_type frametype = frame->frametype;
02269 
02270       bridge_frame_free(frame);
02271       frame = NULL;
02272 
02273       ao2_cleanup(hook);
02274 
02275       switch (frametype) {
02276       case AST_FRAME_DTMF_BEGIN:
02277          /* Just eat the frame. */
02278          break;
02279       case AST_FRAME_DTMF_END:
02280          ast_bridge_channel_feature_digit(bridge_channel, dtmf[0]);
02281          break;
02282       default:
02283          /* Unexpected frame type. */
02284          ast_assert(0);
02285          break;
02286       }
02287 #ifdef TEST_FRAMEWORK
02288    } else if (frame->frametype == AST_FRAME_DTMF_END) {
02289       /* Only transmit this event on DTMF end or else every DTMF
02290        * press will result in the event being broadcast twice
02291        */
02292       ast_test_suite_event_notify("FEATURE_DETECTION", "Result: fail");
02293 #endif
02294    }
02295 
02296    return frame;
02297 }

static void bridge_handle_trip ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 2306 of file bridge_channel.c.

References ast_bridge_channel_kick(), AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_read(), ast_read_noaudio(), bridge_channel_write_frame(), bridge_frame_free(), bridge_handle_dtmf(), ast_bridge_channel::chan, ast_bridge_features::dtmf_passthrough, ast_bridge_channel::features, ast_frame::frametype, ast_frame_subclass::integer, ast_bridge_features::mute, and ast_frame::subclass.

Referenced by bridge_channel_wait().

02307 {
02308    struct ast_frame *frame;
02309 
02310    if (bridge_channel->features->mute) {
02311       frame = ast_read_noaudio(bridge_channel->chan);
02312    } else {
02313       frame = ast_read(bridge_channel->chan);
02314    }
02315 
02316    if (!frame) {
02317       ast_bridge_channel_kick(bridge_channel, 0);
02318       return;
02319    }
02320    switch (frame->frametype) {
02321    case AST_FRAME_CONTROL:
02322       switch (frame->subclass.integer) {
02323       case AST_CONTROL_HANGUP:
02324          ast_bridge_channel_kick(bridge_channel, 0);
02325          bridge_frame_free(frame);
02326          return;
02327       default:
02328          break;
02329       }
02330       break;
02331    case AST_FRAME_DTMF_BEGIN:
02332    case AST_FRAME_DTMF_END:
02333       frame = bridge_handle_dtmf(bridge_channel, frame);
02334       if (!frame) {
02335          return;
02336       }
02337       if (!bridge_channel->features->dtmf_passthrough) {
02338          bridge_frame_free(frame);
02339          return;
02340       }
02341       break;
02342    default:
02343       break;
02344    }
02345 
02346    /* Simply write the frame out to the bridge technology. */
02347    bridge_channel_write_frame(bridge_channel, frame);
02348    bridge_frame_free(frame);
02349 }

static void bridge_sync_cleanup ( struct bridge_sync sync_struct  )  [static]

Clean up a syncrhonization bridge object.

This frees fields within the synchronization object and removes it from the list of active synchronization objects.

Since synchronization objects are stack-allocated, it is vital that this is called before the synchronization object goes out of scope.

Parameters:
sync_struct Synchronization object to clean up.

Definition at line 146 of file bridge_channel.c.

References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_sem_destroy(), bridge_sync::id, bridge_sync::list, and bridge_sync::sem.

Referenced by bridge_channel_queue_action_data_sync().

00147 {
00148    struct bridge_sync *iter;
00149 
00150    AST_RWLIST_WRLOCK(&sync_structs);
00151    AST_LIST_TRAVERSE_SAFE_BEGIN(&sync_structs, iter, list) {
00152       if (iter->id == sync_struct->id) {
00153          AST_LIST_REMOVE_CURRENT(list);
00154          break;
00155       }
00156    }
00157    AST_LIST_TRAVERSE_SAFE_END;
00158    AST_RWLIST_UNLOCK(&sync_structs);
00159 
00160    ast_sem_destroy(&sync_struct->sem);
00161 }

static void bridge_sync_init ( struct bridge_sync sync_struct,
unsigned int  id 
) [static]

initialize a synchronous bridge object.

This both initializes the structure and adds it to the list of synchronization structures.

Parameters:
sync_struct The synchronization object to initialize.
id ID to assign to the synchronization object.

Definition at line 123 of file bridge_channel.c.

References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and ast_sem_init().

Referenced by bridge_channel_queue_action_data_sync().

00124 {
00125    memset(sync_struct, 0, sizeof(*sync_struct));
00126    sync_struct->id = id;
00127    ast_sem_init(&sync_struct->sem, 0, 0);
00128 
00129    AST_RWLIST_WRLOCK(&sync_structs);
00130    AST_RWLIST_INSERT_TAIL(&sync_structs, sync_struct, list);
00131    AST_RWLIST_UNLOCK(&sync_structs);
00132 }

static void bridge_sync_signal ( struct bridge_sync sync_struct  )  [static]

Signal that waiting for a synchronous bridge action is no longer necessary.

This may occur for several reasons

  • The synchronous bridge action has completed.
  • The bridge channel has been removed from the bridge.
  • The synchronous bridge action could not be queued.
Parameters:
sync_struct Synchronization object corresponding to the bridge action.

Definition at line 205 of file bridge_channel.c.

References ast_sem_post(), and bridge_sync::sem.

Referenced by bridge_frame_free().

00206 {
00207    ast_sem_post(&sync_struct->sem);
00208 }

static void bridge_sync_wait ( struct bridge_sync sync_struct  )  [static]

Wait for a synchronous bridge action to complete.

Parameters:
sync_struct Synchronization object corresponding to the bridge action.

Definition at line 184 of file bridge_channel.c.

References ast_samp2tv(), ast_sem_timedwait(), ast_tvadd(), ast_tvnow(), PLAYBACK_TIMEOUT, and bridge_sync::sem.

Referenced by bridge_channel_queue_action_data_sync().

00185 {
00186    struct timeval timeout_val = ast_tvadd(ast_tvnow(), ast_samp2tv(PLAYBACK_TIMEOUT, 1000));
00187    struct timespec timeout_spec = {
00188       .tv_sec = timeout_val.tv_sec,
00189       .tv_nsec = timeout_val.tv_usec * 1000,
00190    };
00191 
00192    ast_sem_timedwait(&sync_struct->sem, &timeout_spec);
00193 }

static void channel_fill_empty_accountcode ( struct ast_channel dest,
struct ast_channel src 
) [static]

Definition at line 427 of file bridge_channel.c.

References ast_channel_accountcode(), ast_channel_name(), ast_channel_peeraccount(), ast_debug, and ast_strlen_zero.

Referenced by channel_set_empty_accountcodes().

00428 {
00429    if (ast_strlen_zero(ast_channel_accountcode(dest))
00430       && !ast_strlen_zero(ast_channel_peeraccount(src))) {
00431       ast_debug(1, "Setting channel %s accountcode with channel %s peeraccount '%s'.\n",
00432          ast_channel_name(dest),
00433          ast_channel_name(src), ast_channel_peeraccount(src));
00434       ast_channel_accountcode_set(dest, ast_channel_peeraccount(src));
00435    }
00436 }

static void channel_fill_empty_peeraccount ( struct ast_channel dest,
struct ast_channel src 
) [static]

Definition at line 404 of file bridge_channel.c.

References ast_channel_accountcode(), ast_channel_name(), ast_channel_peeraccount(), ast_debug, and ast_strlen_zero.

Referenced by channel_set_empty_accountcodes().

00405 {
00406    if (ast_strlen_zero(ast_channel_peeraccount(dest))
00407       && !ast_strlen_zero(ast_channel_accountcode(src))) {
00408       ast_debug(1, "Setting channel %s peeraccount with channel %s accountcode '%s'.\n",
00409          ast_channel_name(dest),
00410          ast_channel_name(src), ast_channel_accountcode(src));
00411       ast_channel_peeraccount_set(dest, ast_channel_accountcode(src));
00412    }
00413 }

static int channel_set_cause ( struct ast_channel chan,
int  cause 
) [static]

Definition at line 266 of file bridge_channel.c.

References AST_CAUSE_NORMAL_CLEARING, ast_channel_hangupcause(), ast_channel_hangupcause_set(), ast_channel_lock, and ast_channel_unlock.

Referenced by ast_bridge_channel_kick(), and ast_bridge_channel_leave_bridge_nolock().

00267 {
00268    ast_channel_lock(chan);
00269    if (cause <= 0) {
00270       cause = ast_channel_hangupcause(chan);
00271       if (cause <= 0) {
00272          cause = AST_CAUSE_NORMAL_CLEARING;
00273       }
00274    }
00275    ast_channel_hangupcause_set(chan, cause);
00276    ast_channel_unlock(chan);
00277    return cause;
00278 }

static void channel_set_empty_accountcodes ( struct ast_channel c0,
struct ast_channel c1 
) [static]

Definition at line 450 of file bridge_channel.c.

References channel_fill_empty_accountcode(), and channel_fill_empty_peeraccount().

Referenced by bridge_channel_update_accountcodes_joining(), and bridge_channel_update_accountcodes_leaving().

00451 {
00452    /* Set empty peeraccount from the other channel's accountcode. */
00453    channel_fill_empty_peeraccount(c0, c1);
00454    channel_fill_empty_peeraccount(c1, c0);
00455 
00456    /* Set empty accountcode from the other channel's peeraccount. */
00457    channel_fill_empty_accountcode(c0, c1);
00458    channel_fill_empty_accountcode(c1, c0);
00459 }

static void channel_update_peeraccount ( struct ast_channel dest,
struct ast_channel src 
) [static]

Definition at line 473 of file bridge_channel.c.

References ast_channel_accountcode(), ast_channel_name(), ast_channel_peeraccount(), and ast_debug.

Referenced by channel_update_peeraccounts().

00474 {
00475    if (strcmp(ast_channel_accountcode(src), ast_channel_peeraccount(dest))) {
00476       ast_debug(1, "Changing channel %s peeraccount '%s' to match channel %s accountcode '%s'.\n",
00477          ast_channel_name(dest), ast_channel_peeraccount(dest),
00478          ast_channel_name(src), ast_channel_accountcode(src));
00479       ast_channel_peeraccount_set(dest, ast_channel_accountcode(src));
00480    }
00481 }

static void channel_update_peeraccounts ( struct ast_channel c0,
struct ast_channel c1 
) [static]

static int payload_helper_app ( ast_bridge_channel_post_action_data  post_it,
struct ast_bridge_channel bridge_channel,
const char *  app_name,
const char *  app_args,
const char *  moh_class 
) [static]

Definition at line 1091 of file bridge_channel.c.

References bridge_run_app::app_args_offset, bridge_run_app::app_name, ast_strlen_zero, BRIDGE_CHANNEL_ACTION_RUN_APP, and bridge_run_app::moh_offset.

Referenced by ast_bridge_channel_queue_app(), and ast_bridge_channel_write_app().

01093 {
01094    struct bridge_run_app *app_data;
01095    size_t len_name = strlen(app_name) + 1;
01096    size_t len_args = ast_strlen_zero(app_args) ? 0 : strlen(app_args) + 1;
01097    size_t len_moh = !moh_class ? 0 : strlen(moh_class) + 1;
01098    size_t len_data = sizeof(*app_data) + len_name + len_args + len_moh;
01099 
01100    /* Fill in application run frame data. */
01101    app_data = alloca(len_data);
01102    app_data->app_args_offset = len_args ? len_name : 0;
01103    app_data->moh_offset = len_moh ? len_name + len_args : 0;
01104    strcpy(app_data->app_name, app_name);/* Safe */
01105    if (len_args) {
01106       strcpy(&app_data->app_name[app_data->app_args_offset], app_args);/* Safe */
01107    }
01108    if (moh_class) {
01109       strcpy(&app_data->app_name[app_data->moh_offset], moh_class);/* Safe */
01110    }
01111 
01112    return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_RUN_APP, app_data, len_data);
01113 }

static int payload_helper_cb ( ast_bridge_channel_post_action_data  post_it,
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 
) [static]

Definition at line 1263 of file bridge_channel.c.

References ast_assert, BRIDGE_CHANNEL_ACTION_CALLBACK, bridge_custom_callback::callback, bridge_custom_callback::flags, bridge_custom_callback::payload, bridge_custom_callback::payload_exists, and bridge_custom_callback::payload_size.

Referenced by ast_bridge_channel_queue_callback(), and ast_bridge_channel_write_callback().

01267 {
01268    struct bridge_custom_callback *cb_data;
01269    size_t len_data = sizeof(*cb_data) + (payload ? payload_size : 0);
01270 
01271    /* Sanity check. */
01272    if (!callback) {
01273       ast_assert(0);
01274       return -1;
01275    }
01276 
01277    /* Fill in custom callback frame data. */
01278    cb_data = alloca(len_data);
01279    cb_data->callback = callback;
01280    cb_data->payload_size = payload_size;
01281    cb_data->flags = flags;
01282    cb_data->payload_exists = payload && payload_size;
01283    if (cb_data->payload_exists) {
01284       memcpy(cb_data->payload, payload, payload_size);/* Safe */
01285    }
01286 
01287    return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_CALLBACK, cb_data, len_data);
01288 }

static int payload_helper_park ( ast_bridge_channel_post_action_data  post_it,
struct ast_bridge_channel bridge_channel,
const char *  parkee_uuid,
const char *  parker_uuid,
const char *  app_data 
) [static]

Definition at line 1337 of file bridge_channel.c.

References bridge_park::app_data_offset, BRIDGE_CHANNEL_ACTION_PARK, bridge_park::parkee_uuid, and bridge_park::parker_uuid_offset.

Referenced by ast_bridge_channel_write_park().

01342 {
01343    struct bridge_park *payload;
01344    size_t len_parkee_uuid = strlen(parkee_uuid) + 1;
01345    size_t len_parker_uuid = strlen(parker_uuid) + 1;
01346    size_t len_app_data = !app_data ? 0 : strlen(app_data) + 1;
01347    size_t len_payload = sizeof(*payload) + len_parker_uuid + len_parkee_uuid + len_app_data;
01348 
01349    payload = alloca(len_payload);
01350    payload->app_data_offset = len_app_data ? len_parkee_uuid + len_parker_uuid : 0;
01351    payload->parker_uuid_offset = len_parkee_uuid;
01352    strcpy(payload->parkee_uuid, parkee_uuid);
01353    strcpy(&payload->parkee_uuid[payload->parker_uuid_offset], parker_uuid);
01354    if (app_data) {
01355       strcpy(&payload->parkee_uuid[payload->app_data_offset], app_data);
01356    }
01357 
01358    return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_PARK, payload, len_payload);
01359 }

static int payload_helper_playfile ( ast_bridge_channel_post_action_data  post_it,
struct ast_bridge_channel bridge_channel,
ast_bridge_custom_play_fn  custom_play,
const char *  playfile,
const char *  moh_class 
) [static]

Definition at line 1184 of file bridge_channel.c.

References ast_alloca, BRIDGE_CHANNEL_ACTION_PLAY_FILE, bridge_playfile::custom_play, bridge_playfile::moh_offset, and bridge_playfile::playfile.

Referenced by ast_bridge_channel_queue_playfile(), ast_bridge_channel_queue_playfile_sync(), and ast_bridge_channel_write_playfile().

01186 {
01187    struct bridge_playfile *payload;
01188    size_t len_name = strlen(playfile) + 1;
01189    size_t len_moh = !moh_class ? 0 : strlen(moh_class) + 1;
01190    size_t len_payload = sizeof(*payload) + len_name + len_moh;
01191 
01192    /* Fill in play file frame data. */
01193    payload = ast_alloca(len_payload);
01194    payload->custom_play = custom_play;
01195    payload->moh_offset = len_moh ? len_name : 0;
01196    strcpy(payload->playfile, playfile);/* Safe */
01197    if (moh_class) {
01198       strcpy(&payload->playfile[payload->moh_offset], moh_class);/* Safe */
01199    }
01200 
01201    return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_PLAY_FILE, payload, len_payload);
01202 }

static void pipe_close ( int *  my_pipe  )  [static]

Definition at line 2745 of file bridge_channel.c.

Referenced by bridge_channel_destroy().

02746 {
02747    if (my_pipe[0] > -1) {
02748       close(my_pipe[0]);
02749       my_pipe[0] = -1;
02750    }
02751    if (my_pipe[1] > -1) {
02752       close(my_pipe[1]);
02753       my_pipe[1] = -1;
02754    }
02755 }

static int pipe_init_nonblock ( int *  my_pipe  )  [static]

Definition at line 2767 of file bridge_channel.c.

References ast_log, errno, and LOG_WARNING.

Referenced by bridge_channel_internal_alloc().

02768 {
02769    int flags;
02770 
02771    my_pipe[0] = -1;
02772    my_pipe[1] = -1;
02773    if (pipe(my_pipe)) {
02774       ast_log(LOG_WARNING, "Can't create pipe! Try increasing max file descriptors with ulimit -n\n");
02775       return -1;
02776    }
02777    flags = fcntl(my_pipe[0], F_GETFL);
02778    if (fcntl(my_pipe[0], F_SETFL, flags | O_NONBLOCK) < 0) {
02779       ast_log(LOG_WARNING, "Unable to set read pipe nonblocking! (%d: %s)\n",
02780          errno, strerror(errno));
02781       return -1;
02782    }
02783    flags = fcntl(my_pipe[1], F_GETFL);
02784    if (fcntl(my_pipe[1], F_SETFL, flags | O_NONBLOCK) < 0) {
02785       ast_log(LOG_WARNING, "Unable to set write pipe nonblocking! (%d: %s)\n",
02786          errno, strerror(errno));
02787       return -1;
02788    }
02789    return 0;
02790 }

static int run_app_helper ( struct ast_channel chan,
const char *  app_name,
const char *  app_args 
) [static]

Definition at line 1017 of file bridge_channel.c.

References app, ast_app_exec_macro(), ast_app_exec_sub(), ast_free, ast_log, ast_str_buffer(), ast_str_create(), ast_str_substitute_variables(), LOG_WARNING, NULL, pbx_exec(), and pbx_findapp().

Referenced by ast_bridge_channel_run_app().

01018 {
01019    int res = 0;
01020 
01021    if (!strcasecmp("Gosub", app_name)) {
01022       ast_app_exec_sub(NULL, chan, app_args, 0);
01023    } else if (!strcasecmp("Macro", app_name)) {
01024       ast_app_exec_macro(NULL, chan, app_args);
01025    } else {
01026       struct ast_app *app;
01027 
01028       app = pbx_findapp(app_name);
01029       if (!app) {
01030          ast_log(LOG_WARNING, "Could not find application (%s)\n", app_name);
01031       } else {
01032          struct ast_str *substituted_args = ast_str_create(16);
01033 
01034          if (substituted_args) {
01035             ast_str_substitute_variables(&substituted_args, 0, chan, app_args);
01036             res = pbx_exec(chan, app, ast_str_buffer(substituted_args));
01037             ast_free(substituted_args);
01038          } else {
01039             ast_log(LOG_WARNING, "Could not substitute application argument variables for %s\n", app_name);
01040             res = pbx_exec(chan, app, app_args);
01041          }
01042       }
01043    }
01044    return res;
01045 }

static void testsuite_notify_feature_success ( struct ast_channel chan,
const char *  dtmf 
) [static]

Definition at line 1481 of file bridge_channel.c.

References ao2_cleanup, ast_get_chan_featuremap_config(), ast_get_chan_features_xfer_config(), ast_test_suite_event_notify, ast_featuremap_config::atxfer, ast_features_xfer_config::atxferthreeway, ast_featuremap_config::automixmon, ast_featuremap_config::automon, ast_featuremap_config::blindxfer, ast_featuremap_config::disconnect, and ast_featuremap_config::parkcall.

Referenced by ast_bridge_channel_feature_digit().

01482 {
01483 #ifdef TEST_FRAMEWORK
01484    char *feature = "unknown";
01485    struct ast_featuremap_config *featuremap = ast_get_chan_featuremap_config(chan);
01486    struct ast_features_xfer_config *xfer = ast_get_chan_features_xfer_config(chan);
01487 
01488    if (featuremap) {
01489       if (!strcmp(dtmf, featuremap->blindxfer)) {
01490          feature = "blindxfer";
01491       } else if (!strcmp(dtmf, featuremap->atxfer)) {
01492          feature = "atxfer";
01493       } else if (!strcmp(dtmf, featuremap->disconnect)) {
01494          feature = "disconnect";
01495       } else if (!strcmp(dtmf, featuremap->automon)) {
01496          feature = "automon";
01497       } else if (!strcmp(dtmf, featuremap->automixmon)) {
01498          feature = "automixmon";
01499       } else if (!strcmp(dtmf, featuremap->parkcall)) {
01500          feature = "parkcall";
01501       }
01502    }
01503    if (xfer) {
01504       if (!strcmp(dtmf, xfer->atxferthreeway)) {
01505          feature = "atxferthreeway";
01506       }
01507    }
01508 
01509    ao2_cleanup(featuremap);
01510    ao2_cleanup(xfer);
01511 
01512    ast_test_suite_event_notify("FEATURE_DETECTION",
01513          "Result: success\r\n"
01514          "Feature: %s", feature);
01515 #endif /* TEST_FRAMEWORK */
01516 }


Variable Documentation

int sync_ids [static]

Counter used for assigning synchronous bridge action IDs.

Definition at line 77 of file bridge_channel.c.


Generated on Thu Apr 16 06:29:10 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6