Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Data Structures | Macros | Typedefs | Functions | Variables
bridge_channel.c File Reference

Bridging Channel API. More...

#include "asterisk.h"
#include <signal.h>
#include "asterisk/heap.h"
#include "asterisk/alertpipe.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 "asterisk/stream.h"
#include "asterisk/message.h"
#include "asterisk/core_local.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...
 

Macros

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

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

Functions

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. More...
 
void ast_bridge_channel_feature_digit_add (struct ast_bridge_channel *bridge_channel, int digit)
 Add a DTMF digit to the collected digits. More...
 
struct ast_channelast_bridge_channel_get_chan (struct ast_bridge_channel *bridge_channel)
 Get a ref to the bridge_channel's ast_channel. More...
 
void ast_bridge_channel_kick (struct ast_bridge_channel *bridge_channel, int cause)
 Kick the channel out of the bridge. More...
 
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). More...
 
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). More...
 
void ast_bridge_channel_lock_bridge (struct ast_bridge_channel *bridge_channel)
 Lock the bridge associated with the bridge channel. More...
 
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. More...
 
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. More...
 
struct ast_bridge_channelast_bridge_channel_peer (struct ast_bridge_channel *bridge_channel)
 Get the peer bridge channel of a two party bridge. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
int ast_bridge_channel_queue_frame (struct ast_bridge_channel *bridge_channel, struct ast_frame *fr)
 Write a frame to the specified bridge_channel. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
void ast_bridge_channel_stream_map (struct ast_bridge_channel *bridge_channel)
 Maps a channel's stream topology to and from the bridge. More...
 
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. More...
 
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. More...
 
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. More...
 
int ast_bridge_channel_write_hold (struct ast_bridge_channel *bridge_channel, const char *moh_class)
 Write a hold frame into the bridge. More...
 
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. More...
 
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. More...
 
int ast_bridge_channel_write_unhold (struct ast_bridge_channel *bridge_channel)
 Write an unhold frame into the bridge. More...
 
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. More...
 
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_cancel_owed_events (struct ast_bridge_channel *bridge_channel)
 
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)
 
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_push_full (struct ast_bridge_channel *bridge_channel, int optimized)
 
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)
 
void bridge_channel_queue_deferred_frames (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)
 
static void bridge_handle_trip (struct ast_bridge_channel *bridge_channel)
 
static void bridge_sync_cleanup (struct bridge_sync *sync_struct)
 Clean up a synchronization bridge object. More...
 
static void bridge_sync_init (struct bridge_sync *sync_struct, unsigned int id)
 Initialize a synchronous bridge object. More...
 
static void bridge_sync_signal (struct bridge_sync *sync_struct)
 Signal that waiting for a synchronous bridge action is no longer necessary. More...
 
static void bridge_sync_wait (struct bridge_sync *sync_struct)
 Wait for a synchronous bridge action to complete. More...
 
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 int run_app_helper (struct ast_channel *chan, const char *app_name, const char *app_args)
 
static void sendtext_safe (struct ast_channel *chan, const struct ast_frame *f)
 
static void testsuite_notify_feature_success (struct ast_channel *chan, const char *dtmf)
 

Variables

static const char * controls []
 
static int sync_ids
 Counter used for assigning synchronous bridge action IDs. More...
 
static struct sync_structs sync_structs = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 

Detailed Description

Bridging Channel API.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om
Richard Mudgett rmudg.nosp@m.ett@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Matt Jordan mjord.nosp@m.an@d.nosp@m.igium.nosp@m..com

Definition in file bridge_channel.c.

Macro Definition Documentation

◆ PLAYBACK_TIMEOUT

#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 179 of file bridge_channel.c.

Typedef Documentation

◆ ast_bridge_channel_post_action_data

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_channelWhich channel work with.
actionType of bridge action frame.
dataFrame payload data to pass.
datalenFrame payload data length to pass.
Return values
0on success.
-1on error.

Definition at line 74 of file bridge_channel.c.

Function Documentation

◆ after_bridge_move_channel()

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

Definition at line 1887 of file bridge_channel.c.

1888{
1889 RAII_VAR(struct ast_channel *, chan_target, data, ao2_cleanup);
1890 struct ast_party_connected_line connected_target;
1891 unsigned char connected_line_data[1024];
1892 int payload_size;
1893
1894 ast_party_connected_line_init(&connected_target);
1895
1896 ast_channel_lock(chan_target);
1897 ast_party_connected_line_copy(&connected_target, ast_channel_connected(chan_target));
1898 ast_channel_unlock(chan_target);
1899 ast_party_id_reset(&connected_target.priv);
1900
1901 if (ast_channel_move(chan_target, chan_bridged)) {
1902 ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
1903 ast_party_connected_line_free(&connected_target);
1904 return;
1905 }
1906
1907 /* The ast_channel_move function will end up updating the connected line information
1908 * on chan_target to the value we have here, but will not inform it. To ensure that
1909 * AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO is executed we wipe it away here. If
1910 * we don't do this then the change will be considered redundant, since the connected
1911 * line information is already there (despite the channel not being told).
1912 */
1913 ast_channel_lock(chan_target);
1916 ast_channel_unlock(chan_target);
1917
1918 if ((payload_size = ast_connected_line_build_data(connected_line_data,
1919 sizeof(connected_line_data), &connected_target, NULL)) != -1) {
1920 struct ast_control_read_action_payload *frame_payload;
1921 int frame_size;
1922
1923 frame_size = payload_size + sizeof(*frame_payload);
1924 frame_payload = ast_alloca(frame_size);
1926 frame_payload->payload_size = payload_size;
1927 memcpy(frame_payload->payload, connected_line_data, payload_size);
1928 ast_queue_control_data(chan_target, AST_CONTROL_READ_ACTION, frame_payload, frame_size);
1929 }
1930
1931 /* A connected line update is queued so that if chan_target is remotely involved with
1932 * anything (such as dialing a channel) the other channel(s) will be informed of the
1933 * new channel they are involved with.
1934 */
1935 ast_channel_lock(chan_target);
1936 ast_connected_line_copy_from_caller(&connected_target, ast_channel_caller(chan_target));
1937 ast_channel_queue_connected_line_update(chan_target, &connected_target, NULL);
1938 ast_channel_unlock(chan_target);
1939
1940 ast_party_connected_line_free(&connected_target);
1941}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2039
#define ast_channel_lock(chan)
Definition: channel.h:2972
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
Definition: channel.c:1998
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition: channel.c:1276
int ast_channel_move(struct ast_channel *dest, struct ast_channel *source)
Move a channel from its current location to a new location.
Definition: channel.c:10671
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2440
void ast_party_id_reset(struct ast_party_id *id)
Destroy and initialize the given party id structure.
Definition: channel.c:1863
int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Build the connected line information data frame.
Definition: channel.c:8702
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:1989
struct ast_party_connected_line * ast_channel_connected_indicated(struct ast_channel *chan)
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8298
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Queue a connected line update frame on a channel.
Definition: channel.c:9111
#define ast_channel_unlock(chan)
Definition: channel.h:2973
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1141
static int frame_size[4]
Definition: format_g726.c:52
@ AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO
@ AST_CONTROL_READ_ACTION
#define NULL
Definition: resample.c:96
Main Channel structure associated with a channel.
enum ast_frame_read_action action
Connected Line/Party information.
Definition: channel.h:458
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ast_control_read_action_payload::action, ao2_cleanup, ast_alloca, ast_channel_caller(), ast_channel_connected(), ast_channel_connected_indicated(), ast_channel_lock, ast_channel_move(), ast_channel_queue_connected_line_update(), ast_channel_unlock, ast_connected_line_build_data(), ast_connected_line_copy_from_caller(), 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_control_read_action_payload::payload, ast_control_read_action_payload::payload_size, ast_party_connected_line::priv, and RAII_VAR.

Referenced by bridge_channel_attended_transfer().

◆ after_bridge_move_channel_fail()

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

Definition at line 1947 of file bridge_channel.c.

1948{
1949 RAII_VAR(struct ast_channel *, chan_target, data, ao2_cleanup);
1950
1951 ast_log(LOG_WARNING, "Unable to complete transfer: %s\n",
1953 ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
1954}
#define ast_log
Definition: astobj2.c:42
const char * ast_bridge_after_cb_reason_string(enum ast_bridge_after_cb_reason reason)
Get a string representation of an after bridge callback reason.
Definition: bridge_after.c:288
#define LOG_WARNING

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

◆ ast_bridge_channel_feature_digit()

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_channelChannel that received a DTMF digit.
digitDTMF digit to add to collected digits or 0 for timeout event.
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.

Definition at line 1705 of file bridge_channel.c.

1706{
1707 struct ast_bridge_features *features = bridge_channel->features;
1708 struct ast_bridge_hook_dtmf *hook = NULL;
1709 size_t dtmf_len;
1710
1711 struct sanity_check_of_dtmf_size {
1712 char check[1 / (ARRAY_LEN(bridge_channel->dtmf_hook_state.collected) == ARRAY_LEN(hook->dtmf.code))];
1713 };
1714
1715 dtmf_len = strlen(bridge_channel->dtmf_hook_state.collected);
1716 if (!dtmf_len && !digit) {
1717 /* Nothing to do */
1718 return;
1719 }
1720
1721 if (digit) {
1722 dtmf_len = bridge_channel_feature_digit_add(bridge_channel, digit, dtmf_len);
1723 }
1724
1725 while (digit) {
1726 /* See if a DTMF feature hook matches or can match */
1727 hook = ao2_find(features->dtmf_hooks, bridge_channel->dtmf_hook_state.collected,
1729 if (!hook) {
1730 ast_debug(1, "No DTMF feature hooks on %p(%s) match '%s'\n",
1731 bridge_channel, ast_channel_name(bridge_channel->chan),
1732 bridge_channel->dtmf_hook_state.collected);
1733 break;
1734 } else if (dtmf_len != strlen(hook->dtmf.code)) {
1735 unsigned int digit_timeout;
1736 /* Need more digits to match */
1737 ao2_ref(hook, -1);
1738 digit_timeout = bridge_channel_feature_digit_timeout(bridge_channel);
1739 bridge_channel->dtmf_hook_state.interdigit_timeout =
1740 ast_tvadd(ast_tvnow(), ast_samp2tv(digit_timeout, 1000));
1741 return;
1742 } else {
1743 int remove_me;
1744 int already_suspended;
1745
1746 ast_debug(1, "DTMF feature hook %p matched DTMF string '%s' on %p(%s)\n",
1747 hook, bridge_channel->dtmf_hook_state.collected, bridge_channel,
1748 ast_channel_name(bridge_channel->chan));
1749
1750 /*
1751 * Clear the collected digits before executing the hook
1752 * in case the hook starts another sequence.
1753 */
1754 bridge_channel->dtmf_hook_state.collected[0] = '\0';
1755
1756 ast_bridge_channel_lock_bridge(bridge_channel);
1757 already_suspended = bridge_channel->suspended;
1758 if (!already_suspended) {
1760 }
1761 ast_bridge_unlock(bridge_channel->bridge);
1762 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
1763
1764 /* Execute the matched hook on this channel. */
1765 remove_me = hook->generic.callback(bridge_channel, hook->generic.hook_pvt);
1766 if (remove_me) {
1767 ast_debug(1, "DTMF hook %p is being removed from %p(%s)\n",
1768 hook, bridge_channel, ast_channel_name(bridge_channel->chan));
1769 ao2_unlink(features->dtmf_hooks, hook);
1770 }
1771 testsuite_notify_feature_success(bridge_channel->chan, hook->dtmf.code);
1772 ao2_ref(hook, -1);
1773
1774 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
1775 if (!already_suspended) {
1776 bridge_channel_unsuspend(bridge_channel);
1777 }
1778
1779 /*
1780 * If we are handing the channel off to an external hook for
1781 * ownership, we are not guaranteed what kind of state it will
1782 * come back in. If the channel hungup, we need to detect that
1783 * here if the hook did not already change the state.
1784 */
1785 if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) {
1786 ast_bridge_channel_kick(bridge_channel, 0);
1787 bridge_channel->dtmf_hook_state.collected[0] = '\0';
1788 return;
1789 }
1790
1791 /* if there is dtmf that has been collected then loop back through,
1792 but set digit to -1 so it doesn't try to do an add since the dtmf
1793 is already in the buffer */
1794 dtmf_len = strlen(bridge_channel->dtmf_hook_state.collected);
1795 if (!dtmf_len) {
1796 return;
1797 }
1798 }
1799 }
1800
1801 if (!digit) {
1802 ast_debug(1, "DTMF feature string collection on %p(%s) timed out\n",
1803 bridge_channel, ast_channel_name(bridge_channel->chan));
1804 }
1805
1806 /* Timeout or DTMF digit didn't allow a match with any hooks. */
1807 if (features->dtmf_passthrough) {
1808 /* Stream the collected DTMF to the other channels. */
1809 bridge_channel_write_dtmf_stream(bridge_channel,
1810 bridge_channel->dtmf_hook_state.collected);
1811 }
1812 bridge_channel->dtmf_hook_state.collected[0] = '\0';
1813
1814 ast_test_suite_event_notify("FEATURE_DETECTION", "Result: fail");
1815}
char digit
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:485
static void testsuite_notify_feature_success(struct ast_channel *chan, const char *dtmf)
void bridge_channel_internal_suspend_nolock(struct ast_bridge_channel *bridge_channel)
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
Lock the bridge associated with the bridge channel.
void ast_bridge_channel_kick(struct ast_bridge_channel *bridge_channel, int cause)
Kick the channel out of the bridge.
static void bridge_channel_unsuspend(struct ast_bridge_channel *bridge_channel)
static int bridge_channel_write_dtmf_stream(struct ast_bridge_channel *bridge_channel, const char *dtmf)
static unsigned int bridge_channel_feature_digit_timeout(struct ast_bridge_channel *bridge_channel)
static int bridge_channel_feature_digit_add(struct ast_bridge_channel *bridge_channel, int digit, size_t dtmf_len)
const char * ast_channel_name(const struct ast_channel *chan)
int ast_check_hangup_locked(struct ast_channel *chan)
Definition: channel.c:458
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4234
@ AST_CONTROL_SRCUPDATE
#define ast_debug(level,...)
Log a DEBUG message.
unsigned int suspended
struct ast_bridge * bridge
Bridge this channel is participating in.
struct timeval interdigit_timeout
char collected[MAXIMUM_DTMF_FEATURE_STRING]
struct ast_bridge_features * features
struct ast_channel * chan
struct ast_bridge_channel::@197 dtmf_hook_state
Structure that contains features information.
struct ao2_container * dtmf_hooks
unsigned int dtmf_passthrough
char code[MAXIMUM_DTMF_FEATURE_STRING]
struct ast_bridge_hook generic
struct ast_bridge_hook_dtmf_parms dtmf
ast_bridge_hook_callback callback
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:189
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:282
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#define ARRAY_LEN(a)
Definition: utils.h:666

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, digit, 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().

◆ ast_bridge_channel_feature_digit_add()

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_channelChannel that received a DTMF digit.
digitDTMF 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 1697 of file bridge_channel.c.

1698{
1699 if (digit) {
1701 bridge_channel, digit, strlen(bridge_channel->dtmf_hook_state.collected));
1702 }
1703}

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

Referenced by play_file().

◆ ast_bridge_channel_get_chan()

struct ast_channel * ast_bridge_channel_get_chan ( struct ast_bridge_channel bridge_channel)

Get a ref to the bridge_channel's ast_channel.

Parameters
bridge_channelThe bridge channel
Note
The returned channel NEEDS to be unref'd once you are done with it. In general, this function is best used when accessing the bridge_channel chan from outside of a bridging thread.
Return values
ref'dast_channel on success
NULLotherwise

Definition at line 212 of file bridge_channel.c.

213{
214 struct ast_channel *chan;
215
219
220 return chan;
221}
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
struct ast_bridge_channel * bridge_channel

References ao2_bump, ao2_lock, ao2_unlock, ast_channel::bridge_channel, and ast_bridge_channel::chan.

Referenced by ast_bridge_channel_write_unhold().

◆ ast_bridge_channel_kick()

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_channelWhich channel is being kicked or hungup.
causeCause 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.

Definition at line 602 of file bridge_channel.c.

603{
604 struct ast_bridge_features *features = bridge_channel->features;
605 struct ast_bridge_hook *hook;
606 struct ao2_iterator iter;
607
608 ast_bridge_channel_lock(bridge_channel);
609 if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
610 channel_set_cause(bridge_channel->chan, cause);
611 cause = 0;
612 }
613 ast_bridge_channel_unlock(bridge_channel);
614
615 /* Run any hangup hooks. */
616 iter = ao2_iterator_init(features->other_hooks, 0);
617 for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
618 int remove_me;
619
620 if (hook->type != AST_BRIDGE_HOOK_TYPE_HANGUP) {
621 continue;
622 }
623 remove_me = hook->callback(bridge_channel, hook->hook_pvt);
624 if (remove_me) {
625 ast_debug(1, "Hangup hook %p is being removed from %p(%s)\n",
626 hook, bridge_channel, ast_channel_name(bridge_channel->chan));
627 ao2_unlink(features->other_hooks, hook);
628 }
629 }
631
632 /* Default hangup action. */
634}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static int channel_set_cause(struct ast_channel *chan, int cause)
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).
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
#define ast_bridge_channel_lock(bridge_channel)
Lock the bridge_channel.
@ BRIDGE_CHANNEL_STATE_WAIT
@ BRIDGE_CHANNEL_STATE_END
@ AST_BRIDGE_HOOK_TYPE_HANGUP
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
enum bridge_channel_state state
struct ao2_container * other_hooks
Structure that is the essence of a feature hook.
enum ast_bridge_hook_type type

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_handle_action(), bridge_channel_internal_join(), bridge_handle_trip(), and kick_it().

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

Parameters
bridge_channelChannel to change the state on
new_stateThe new state to place the channel into
causeCause of channel leaving bridge. If cause <= 0 then use cause on channel if cause still <= 0 use AST_CAUSE_NORMAL_CLEARING.

Example usage:

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).
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:106

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 325 of file bridge_channel.c.

326{
327 ast_bridge_channel_lock(bridge_channel);
328 ast_bridge_channel_leave_bridge_nolock(bridge_channel, new_state, cause);
329 ast_bridge_channel_unlock(bridge_channel);
330}
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).

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_complete_join(), bridge_channel_dissolve_check(), bridge_channel_internal_push_full(), bridge_dissolve(), bridge_do_merge(), bridge_do_move(), bridge_features_duration_callback(), bridge_swap_attended_transfer(), bridgewait_timeout_callback(), caller_joined_bridge(), caller_safety_timeout(), feature_hangup(), parking_duration_callback(), say_parking_space(), set_softmix_bridge_data(), try_swap_optimize_out(), and user_timeout().

◆ ast_bridge_channel_leave_bridge_nolock()

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_channelChannel to change the state on
new_stateThe new state to place the channel into
causeCause 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 303 of file bridge_channel.c.

304{
305 if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
306 return;
307 }
308
309 ast_debug(1, "Setting %p(%s) state from:%u to:%u\n",
310 bridge_channel, ast_channel_name(bridge_channel->chan), bridge_channel->state,
311 new_state);
312
313 channel_set_cause(bridge_channel->chan, cause);
314
315 ast_channel_lock(bridge_channel->chan);
316 ast_bridge_vars_set(bridge_channel->chan, NULL, NULL);
317 ast_channel_unlock(bridge_channel->chan);
318
319 /* Change the state on the bridge channel */
320 bridge_channel->state = new_state;
321
322 bridge_channel_poke(bridge_channel);
323}
void ast_bridge_vars_set(struct ast_channel *chan, const char *name, const char *pvtid)
Sets BRIDGECHANNEL and BRIDGEPVTCALLID for a channel.
Definition: bridge.c:1281
static void bridge_channel_poke(struct ast_bridge_channel *bridge_channel)

References ast_bridge_vars_set(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, bridge_channel_poke(), BRIDGE_CHANNEL_STATE_WAIT, ast_bridge_channel::chan, channel_set_cause(), NULL, and ast_bridge_channel::state.

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

◆ ast_bridge_channel_lock_bridge()

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

Definition at line 223 of file bridge_channel.c.

224{
225 struct ast_bridge *bridge;
226
227 for (;;) {
228 /* Safely get the bridge pointer */
229 ast_bridge_channel_lock(bridge_channel);
230 bridge = bridge_channel->bridge;
231 ao2_ref(bridge, +1);
232 ast_bridge_channel_unlock(bridge_channel);
233
234 /* Lock the bridge and see if it is still the bridge we need to lock. */
235 ast_bridge_lock(bridge);
236 if (bridge == bridge_channel->bridge) {
237 ao2_ref(bridge, -1);
238 return;
239 }
240 ast_bridge_unlock(bridge);
241 ao2_ref(bridge, -1);
242 }
243}
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:474
Structure that contains information about a bridge.
Definition: bridge.h:353

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

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

◆ ast_bridge_channel_merge_inhibit()

struct ast_bridge * ast_bridge_channel_merge_inhibit ( struct ast_bridge_channel bridge_channel,
int  request 
)

Adjust the bridge_channel's bridge merge inhibit request count.

Since
12.0.0
Parameters
bridge_channelWhat to operate on.
requestInhibit request increment. (Positive to add requests. Negative to remove requests.)
Note
This API call is meant for internal bridging operations.
Return values
bridgeadjusted merge inhibit with reference count.

Definition at line 380 of file bridge_channel.c.

381{
382 struct ast_bridge *bridge;
383
384 ast_bridge_channel_lock_bridge(bridge_channel);
385 bridge = bridge_channel->bridge;
386 ao2_ref(bridge, +1);
388 ast_bridge_unlock(bridge);
389 return bridge;
390}
void bridge_merge_inhibit_nolock(struct ast_bridge *bridge, int request)
Definition: bridge.c:3060
static int request(void *obj)
Definition: chan_pjsip.c:2605

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

Referenced by feature_attended_transfer().

◆ ast_bridge_channel_notify_talking()

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_channelThe bridge channel that has either started or stopped talking.
started_talkingset to 1 when this indicates the channel has started talking set to 0 when this indicates the channel has stopped talking.
Return values
0on success.
-1on error.

Definition at line 245 of file bridge_channel.c.

246{
247 struct ast_frame action = {
249 .subclass.integer = started_talking
251 };
252
253 return ast_bridge_channel_queue_frame(bridge_channel, &action);
254}
int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr)
Write a frame to the specified bridge_channel.
@ BRIDGE_CHANNEL_ACTION_TALKING_STOP
@ BRIDGE_CHANNEL_ACTION_TALKING_START
@ AST_FRAME_BRIDGE_ACTION
Data structure associated with a single frame of data.
enum ast_frame_type frametype

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 clear_talking(), and softmix_bridge_write_voice().

◆ ast_bridge_channel_peer()

struct ast_bridge_channel * ast_bridge_channel_peer ( struct ast_bridge_channel bridge_channel)

Get the peer bridge channel of a two party bridge.

Since
12.0.0
Parameters
bridge_channelWhat to get the peer of.
Note
On entry, bridge_channel->bridge is already locked.
This is an internal bridge function.
Return values
peeron success.
NULLno peer channel.

Definition at line 332 of file bridge_channel.c.

333{
334 struct ast_bridge *bridge = bridge_channel->bridge;
335 struct ast_bridge_channel *other = NULL;
336
337 if (bridge_channel->in_bridge && bridge->num_channels == 2) {
339 if (other != bridge_channel) {
340 break;
341 }
342 }
343 }
344
345 return other;
346}
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
Structure that contains information regarding a channel in a bridge.
struct ast_bridge_channel::@193 entry
unsigned int in_bridge
struct ast_bridge_channels_list channels
Definition: bridge.h:367
unsigned int num_channels
Definition: bridge.h:377

References AST_LIST_TRAVERSE, ast_bridge_channel::bridge, ast_bridge::channels, ast_bridge_channel::entry, 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().

◆ ast_bridge_channel_playfile()

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_channelWhich channel to play the file on
custom_playCall this function to play the playfile. (NULL if normal sound file to play)
playfileSound filename to play.
moh_classMOH 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.

Definition at line 1272 of file bridge_channel.c.

1273{
1274 if (moh_class) {
1275 ast_bridge_channel_write_hold(bridge_channel, moh_class);
1276 }
1277 if (custom_play) {
1278 custom_play(bridge_channel, playfile);
1279 } else {
1280 ast_stream_and_wait(bridge_channel->chan, playfile, AST_DIGIT_NONE);
1281 }
1282 if (moh_class) {
1283 ast_bridge_channel_write_unhold(bridge_channel);
1284 }
1285
1286 /*
1287 * It may be necessary to resume music on hold after we finish
1288 * playing the announcement.
1289 */
1290 if (ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_MOH)) {
1291 const char *latest_musicclass;
1292
1293 ast_channel_lock(bridge_channel->chan);
1294 latest_musicclass = ast_strdupa(ast_channel_latest_musicclass(bridge_channel->chan));
1295 ast_channel_unlock(bridge_channel->chan);
1296 ast_moh_start(bridge_channel->chan, latest_musicclass, NULL);
1297 }
1298}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel)
Write an unhold frame into the bridge.
int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, const char *moh_class)
Write a hold frame into the bridge.
const char * ast_channel_latest_musicclass(const struct ast_channel *chan)
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
@ AST_FLAG_MOH
Definition: channel.h:1011
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1886
#define AST_DIGIT_NONE
Definition: file.h:47
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7739
#define ast_test_flag(p, flag)
Definition: utils.h:63

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

◆ ast_bridge_channel_queue_app()

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_channelWhich channel to put the frame onto
app_nameDialplan application name.
app_argsArguments for the application. (NULL or empty for no arguments)
moh_classMOH 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
0on success.
-1on error.

Definition at line 1266 of file bridge_channel.c.

1267{
1269 bridge_channel, app_name, app_args, moh_class);
1270}
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 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)
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463

References app_name(), bridge_channel_queue_action_data(), and payload_helper_app().

◆ ast_bridge_channel_queue_callback()

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_channelWhich channel to put the frame onto.
flagsCustom callback option flags.
callbackCustom callback run on a bridge channel.
payloadData to pass to the callback. (NULL if none).
payload_sizeSize 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
0on success.
-1on error.

Definition at line 1439 of file bridge_channel.c.

1442{
1444 bridge_channel, flags, callback, payload, payload_size);
1445}
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 struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)

References bridge_channel_queue_action_data(), callback(), bridge_custom_callback::flags, bridge_custom_callback::payload, payload_helper_cb(), and bridge_custom_callback::payload_size.

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

◆ ast_bridge_channel_queue_control_data()

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_channelWhich channel to queue the frame onto.
controlType of control frame.
dataFrame payload data to pass.
datalenFrame payload data length to pass.
Return values
0on success.
-1on error.

Definition at line 1114 of file bridge_channel.c.

1115{
1116 struct ast_frame frame = {
1118 .subclass.integer = control,
1119 .datalen = datalen,
1120 .data.ptr = (void *) data,
1121 };
1122
1123 return ast_bridge_channel_queue_frame(bridge_channel, &frame);
1124}
@ AST_FRAME_CONTROL
union ast_frame::@228 data

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

Referenced by bridge_reconfigured_connected_line_update(), and send_colp_to_agent().

◆ ast_bridge_channel_queue_frame()

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_channelChannel to queue the frame.
frFrame to write.
Return values
0on success.
-1on error.

Definition at line 1015 of file bridge_channel.c.

1016{
1017 struct ast_frame *dup;
1018
1019 if (bridge_channel->suspended
1020 /* Also defer DTMF frames. */
1023 && !ast_is_deferrable_frame(fr)) {
1024 /* Drop non-deferable frames when suspended. */
1025 return 0;
1026 }
1027 if (fr->frametype == AST_FRAME_NULL) {
1028 /* "Accept" the frame and discard it. */
1029 return 0;
1030 }
1031
1032 if ((fr->frametype == AST_FRAME_VOICE || fr->frametype == AST_FRAME_VIDEO ||
1034 fr->frametype == AST_FRAME_RTCP) && fr->stream_num > -1) {
1035 int num = -1;
1036
1037 ast_bridge_channel_lock(bridge_channel);
1038 if (fr->stream_num < (int)AST_VECTOR_SIZE(&bridge_channel->stream_map.to_channel)) {
1039 num = AST_VECTOR_GET(&bridge_channel->stream_map.to_channel, fr->stream_num);
1040 }
1041 ast_bridge_channel_unlock(bridge_channel);
1042
1043 if (num == -1) {
1044 /* We don't have a mapped stream so just discard this frame. */
1045 return 0;
1046 }
1047 }
1048
1049 dup = ast_frdup(fr);
1050 if (!dup) {
1051 return -1;
1052 }
1053
1054 ast_bridge_channel_lock(bridge_channel);
1055 if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
1056 /* Drop frames on channels leaving the bridge. */
1057 ast_bridge_channel_unlock(bridge_channel);
1058 bridge_frame_free(dup);
1059 return 0;
1060 }
1061
1062 if ((fr->frametype == AST_FRAME_TEXT || fr->frametype == AST_FRAME_TEXT_DATA) &&
1063 !bridge_channel->features->text_messaging) {
1064 /* This channel is not accepting text messages. */
1065 ast_bridge_channel_unlock(bridge_channel);
1066 bridge_frame_free(dup);
1067 return 0;
1068 }
1069
1070 if (DEBUG_ATLEAST(1)) {
1071 if (fr->frametype == AST_FRAME_TEXT) {
1072 ast_log(LOG_DEBUG, "Queuing TEXT frame to '%s': %*.s\n", ast_channel_name(bridge_channel->chan),
1073 fr->datalen, (char *)fr->data.ptr);
1074 } else if (fr->frametype == AST_FRAME_TEXT_DATA) {
1075 struct ast_msg_data *msg = fr->data.ptr;
1076 ast_log(LOG_DEBUG, "Queueing TEXT_DATA frame from '%s' to '%s:%s': %s\n",
1079 ast_channel_name(bridge_channel->chan),
1081 }
1082 }
1083
1084 AST_LIST_INSERT_TAIL(&bridge_channel->wr_queue, dup, frame_list);
1085 if (ast_alertpipe_write(bridge_channel->alert_pipe)) {
1086 ast_log(LOG_ERROR, "We couldn't write alert pipe for %p(%s)... something is VERY wrong\n",
1087 bridge_channel, ast_channel_name(bridge_channel->chan));
1088 }
1089 ast_bridge_channel_unlock(bridge_channel);
1090 return 0;
1091}
ssize_t ast_alertpipe_write(int alert_pipe[2])
Write an event to an alert pipe.
Definition: alertpipe.c:120
static void bridge_frame_free(struct ast_frame *frame)
int ast_is_deferrable_frame(const struct ast_frame *frame)
Should we keep this frame for later?
Definition: channel.c:1434
const char * ast_msg_data_get_attribute(struct ast_msg_data *msg, enum ast_msg_data_attribute_type attribute_type)
Get attribute from ast_msg_data.
@ AST_MSG_DATA_ATTR_BODY
Definition: message.h:458
@ AST_MSG_DATA_ATTR_TO
Definition: message.h:455
@ AST_MSG_DATA_ATTR_FROM
Definition: message.h:456
#define ast_frdup(fr)
Copies a frame.
@ AST_FRAME_VIDEO
@ AST_FRAME_NULL
@ AST_FRAME_IMAGE
@ AST_FRAME_DTMF_END
@ AST_FRAME_DTMF_BEGIN
@ AST_FRAME_VOICE
@ AST_FRAME_RTCP
@ AST_FRAME_TEXT_DATA
@ AST_FRAME_TEXT
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
#define LOG_ERROR
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
struct ast_bridge_channel::@194 wr_queue
struct ast_bridge_channel::@200 stream_map
struct ast_vector_int to_channel
unsigned int text_messaging
Structure used to transport a message through the frame core.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

References ast_bridge_channel::alert_pipe, ast_alertpipe_write(), ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_channel_name(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_IMAGE, AST_FRAME_NULL, AST_FRAME_RTCP, AST_FRAME_TEXT, AST_FRAME_TEXT_DATA, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup, ast_is_deferrable_frame(), AST_LIST_INSERT_TAIL, ast_log, AST_MSG_DATA_ATTR_BODY, AST_MSG_DATA_ATTR_FROM, AST_MSG_DATA_ATTR_TO, ast_msg_data_get_attribute(), AST_VECTOR_GET, AST_VECTOR_SIZE, BRIDGE_CHANNEL_STATE_WAIT, bridge_frame_free(), ast_bridge_channel::chan, ast_frame::data, ast_frame::datalen, DEBUG_ATLEAST, ast_bridge_channel::features, ast_frame::frametype, LOG_DEBUG, LOG_ERROR, ast_frame::ptr, ast_bridge_channel::state, ast_bridge_channel::stream_map, ast_frame::stream_num, ast_bridge_channel::suspended, ast_bridge_features::text_messaging, ast_bridge_channel::to_channel, 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(), remb_send_report(), send_message(), softmix_mixing_loop(), and softmix_pass_video_top_priority().

◆ ast_bridge_channel_queue_playfile()

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_channelWhich channel to put the frame onto.
custom_playCall this function to play the playfile. (NULL if normal sound file to play)
playfileSound filename to play.
moh_classMOH 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
0on success.
-1on error.

Definition at line 1353 of file bridge_channel.c.

1354{
1356 bridge_channel, custom_play, playfile, moh_class);
1357}
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)

References bridge_channel_queue_action_data(), bridge_playfile::custom_play, payload_helper_playfile(), and bridge_playfile::playfile.

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

◆ ast_bridge_channel_queue_playfile_sync()

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_channelWhich channel to put the frame onto.
custom_playCall this function to play the playfile. (NULL if normal sound file to play)
playfileSound filename to play.
moh_classMOH 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
0The playback was successfully queued.
-1The playback could not be queued.

Definition at line 1359 of file bridge_channel.c.

1361{
1363 bridge_channel, custom_play, playfile, moh_class);
1364}
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)

References bridge_channel_queue_action_data_sync(), bridge_playfile::custom_play, payload_helper_playfile(), and bridge_playfile::playfile.

Referenced by parker_parked_call_message_response(), and play_uri().

◆ ast_bridge_channel_restore_formats()

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_channelChannel to restore

Definition at line 348 of file bridge_channel.c.

349{
350 ast_assert(bridge_channel->read_format != NULL);
351 ast_assert(bridge_channel->write_format != NULL);
352
353 ast_channel_lock(bridge_channel->chan);
354
355 /* Restore original formats of the channel as they came in */
356 if (ast_format_cmp(ast_channel_readformat(bridge_channel->chan), bridge_channel->read_format) == AST_FORMAT_CMP_NOT_EQUAL) {
357 ast_debug(1, "Bridge is returning %p(%s) to read format %s\n",
358 bridge_channel, ast_channel_name(bridge_channel->chan),
359 ast_format_get_name(bridge_channel->read_format));
360 if (ast_set_read_format(bridge_channel->chan, bridge_channel->read_format)) {
361 ast_debug(1, "Bridge failed to return %p(%s) to read format %s\n",
362 bridge_channel, ast_channel_name(bridge_channel->chan),
363 ast_format_get_name(bridge_channel->read_format));
364 }
365 }
366 if (ast_format_cmp(ast_channel_writeformat(bridge_channel->chan), bridge_channel->write_format) == AST_FORMAT_CMP_NOT_EQUAL) {
367 ast_debug(1, "Bridge is returning %p(%s) to write format %s\n",
368 bridge_channel, ast_channel_name(bridge_channel->chan),
369 ast_format_get_name(bridge_channel->write_format));
370 if (ast_set_write_format(bridge_channel->chan, bridge_channel->write_format)) {
371 ast_debug(1, "Bridge failed to return %p(%s) to write format %s\n",
372 bridge_channel, ast_channel_name(bridge_channel->chan),
373 ast_format_get_name(bridge_channel->write_format));
374 }
375 }
376
377 ast_channel_unlock(bridge_channel->chan);
378}
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5721
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5762
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
@ AST_FORMAT_CMP_NOT_EQUAL
Definition: format.h:38
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
struct ast_format * write_format
struct ast_format * read_format
#define ast_assert(a)
Definition: utils.h:739

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

◆ ast_bridge_channel_run_app()

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_channelWhich channel to run the application on.
app_nameDialplan application name.
app_argsArguments for the application. (NULL tolerant)
moh_classMOH 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.

Definition at line 1194 of file bridge_channel.c.

1195{
1196 if (moh_class) {
1197 ast_bridge_channel_write_hold(bridge_channel, moh_class);
1198 }
1199 if (run_app_helper(bridge_channel->chan, app_name, S_OR(app_args, ""))) {
1200 /* Break the bridge if the app returns non-zero. */
1202 }
1203 if (moh_class) {
1204 ast_bridge_channel_write_unhold(bridge_channel);
1205 }
1206}
static int run_app_helper(struct ast_channel *chan, const char *app_name, const char *app_args)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80

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

Referenced by bridge_channel_run_app(), and dynamic_dtmf_hook_callback().

◆ ast_bridge_channel_stream_map()

void ast_bridge_channel_stream_map ( struct ast_bridge_channel bridge_channel)

Maps a channel's stream topology to and from the bridge.

Since
15.0.0

When a channel joins a bridge or its associated stream topology is updated, each stream in the topology needs to be mapped according to its media type to the bridge. Calling this method creates a mapping of each stream on the channel indexed to the bridge's supported media types and vice versa (i.e. bridge's media types indexed to channel streams).

The first channel to join the bridge creates the initial order for the bridge's media types (e.g. a one to one mapping is made). Subsequently added channels are mapped to that order adding more media types if/when the newly added channel has more streams and/or media types specified by the bridge.

Parameters
bridge_channelChannel to map
Note
The bridge_channel's bridge must be locked prior to calling this function.

Definition at line 3129 of file bridge_channel.c.

3130{
3131 ast_bridge_channel_lock(bridge_channel);
3132 ast_channel_lock(bridge_channel->chan);
3134 &bridge_channel->bridge->media_types, &bridge_channel->stream_map.to_bridge,
3135 &bridge_channel->stream_map.to_channel);
3136 ast_channel_unlock(bridge_channel->chan);
3137 ast_bridge_channel_unlock(bridge_channel);
3138}
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
void ast_stream_topology_map(const struct ast_stream_topology *topology, struct ast_vector_int *types, struct ast_vector_int *v0, struct ast_vector_int *v1)
Map a given topology's streams to the given types.
Definition: stream.c:988
struct ast_vector_int to_bridge
struct ast_vector_int media_types
Definition: bridge.h:408

References ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_channel_get_stream_topology(), ast_channel_lock, ast_channel_unlock, ast_stream_topology_map(), ast_bridge_channel::bridge, ast_bridge_channel::chan, ast_bridge::media_types, ast_bridge_channel::stream_map, ast_bridge_channel::to_bridge, and ast_bridge_channel::to_channel.

Referenced by bridge_channel_complete_join(), bridge_handle_trip(), native_rtp_stream_topology_changed(), simple_bridge_stream_topology_changed(), and softmix_bridge_stream_topology_changed().

◆ ast_bridge_channel_update_accountcodes()

void ast_bridge_channel_update_accountcodes ( struct ast_bridge_channel joining,
struct ast_bridge_channel leaving 
)

Definition at line 593 of file bridge_channel.c.

594{
595 if (joining) {
597 } else {
599 }
600}
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)

References bridge_channel_update_accountcodes_joining(), and bridge_channel_update_accountcodes_leaving().

Referenced by bridge_basic_pull(), bridge_basic_push(), bridge_stasis_pull(), and bridge_stasis_push().

◆ ast_bridge_channel_update_linkedids()

void ast_bridge_channel_update_linkedids ( struct ast_bridge_channel bridge_channel,
struct ast_bridge_channel swap 
)

Definition at line 392 of file bridge_channel.c.

393{
394 struct ast_bridge_channel *other;
395 struct ast_bridge *bridge = bridge_channel->bridge;
396 struct ast_channel *oldest_linkedid_chan = bridge_channel->chan;
397
398 AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
399 if (other == swap) {
400 continue;
401 }
402 oldest_linkedid_chan = ast_channel_internal_oldest_linkedid(
403 oldest_linkedid_chan, other->chan);
404 }
405
409 AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
410 if (other == swap) {
411 continue;
412 }
413 ast_channel_lock(other->chan);
414 ast_channel_internal_copy_linkedid(other->chan, oldest_linkedid_chan);
415 ast_channel_unlock(other->chan);
416 }
417}
void ast_channel_internal_copy_linkedid(struct ast_channel *dest, struct ast_channel *source)
Copy the full linkedid channel id structure from one channel to another.
struct ast_channel * ast_channel_internal_oldest_linkedid(struct ast_channel *a, struct ast_channel *b)
Determine which channel has an older linkedid.
struct ast_bridge * bridge

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_channel::bridge, ast_channel::bridge_channel, ast_bridge_channel::chan, and ast_bridge::channels.

Referenced by bridge_basic_push(), and bridge_stasis_push().

◆ ast_bridge_channel_write_app()

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_channelWhich channel is putting the frame into the bridge
app_nameDialplan application name.
app_argsArguments for the application. (NULL or empty for no arguments)
moh_classMOH 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
0on success.
-1on error.

Definition at line 1260 of file bridge_channel.c.

1261{
1263 bridge_channel, app_name, app_args, moh_class);
1264}
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)

References app_name(), bridge_channel_write_action_data(), and payload_helper_app().

◆ ast_bridge_channel_write_callback()

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_channelWhich channel is putting the frame into the bridge
flagsCustom callback option flags.
callbackCustom callback run on a bridge channel.
payloadData to pass to the callback. (NULL if none).
payload_sizeSize 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
0on success.
-1on error.

Definition at line 1431 of file bridge_channel.c.

1434{
1436 bridge_channel, flags, callback, payload, payload_size);
1437}

References bridge_channel_write_action_data(), callback(), bridge_custom_callback::flags, bridge_custom_callback::payload, payload_helper_cb(), and bridge_custom_callback::payload_size.

Referenced by agent_connect_caller(), and dynamic_dtmf_hook_trip().

◆ ast_bridge_channel_write_control_data()

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_channelWhich channel is putting the frame into the bridge.
controlType of control frame.
dataFrame payload data to pass.
datalenFrame payload data length to pass.
Return values
0on success.
-1on error.

Definition at line 1126 of file bridge_channel.c.

1127{
1128 struct ast_frame frame = {
1130 .subclass.integer = control,
1131 .datalen = datalen,
1132 .data.ptr = (void *) data,
1133 };
1134
1135 return bridge_channel_write_frame(bridge_channel, &frame);
1136}
static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)

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

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

◆ ast_bridge_channel_write_hold()

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_channelWhich channel is putting the hold into the bridge.
moh_classThe suggested music class for the other end to use.
Return values
0on success.
-1on error.

Definition at line 1138 of file bridge_channel.c.

1139{
1140 struct ast_json *blob;
1141 int res;
1142 size_t datalen;
1143
1144 if (!ast_strlen_zero(moh_class)) {
1145 datalen = strlen(moh_class) + 1;
1146
1147 blob = ast_json_pack("{s: s}",
1148 "musicclass", moh_class);
1149 } else {
1150 moh_class = NULL;
1151 datalen = 0;
1152 blob = NULL;
1153 }
1154
1156
1158 moh_class, datalen);
1159
1160 ast_json_unref(blob);
1161 return res;
1162}
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.
struct stasis_message_type * ast_channel_hold_type(void)
Message type for when a channel is placed on hold.
void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message using the latest snapshot from the cache.
@ AST_CONTROL_HOLD
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Abstract JSON element (object, array, string, int, ...).

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

◆ ast_bridge_channel_write_park()

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_channelBridge channel performing the parking
parkee_uuidUnique id of the channel we want to park
parker_uuidUnique id of the channel parking the call
app_datastring indicating data used for park application (NULL allowed)
Note
This is intended to be called by bridge hooks.
Return values
0on success.
-1on error.

Definition at line 1502 of file bridge_channel.c.

1503{
1505 bridge_channel, parkee_uuid, parker_uuid, app_data);
1506}
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)

References bridge_channel_write_action_data(), bridge_park::parkee_uuid, and payload_helper_park().

Referenced by manager_park_bridged(), and parking_blind_transfer_park().

◆ ast_bridge_channel_write_playfile()

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_channelWhich channel is putting the frame into the bridge
custom_playCall this function to play the playfile. (NULL if normal sound file to play)
playfileSound filename to play.
moh_classMOH 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
0on success.
-1on error.

Definition at line 1347 of file bridge_channel.c.

1348{
1350 bridge_channel, custom_play, playfile, moh_class);
1351}

References bridge_channel_write_action_data(), bridge_playfile::custom_play, payload_helper_playfile(), and bridge_playfile::playfile.

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

◆ ast_bridge_channel_write_unhold()

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_channelWhich channel is putting the hold into the bridge.
Return values
0on success.
-1on error.

Definition at line 1164 of file bridge_channel.c.

1165{
1167
1168 if (!chan) {
1169 return -1;
1170 }
1171
1173 ao2_ref(chan, -1);
1174
1176}
struct ast_channel * ast_bridge_channel_get_chan(struct ast_bridge_channel *bridge_channel)
Get a ref to the bridge_channel's ast_channel.
struct stasis_message_type * ast_channel_unhold_type(void)
Message type for when a channel is removed from hold.
@ AST_CONTROL_UNHOLD

References ao2_ref, ast_bridge_channel_get_chan(), ast_bridge_channel_write_control_data(), ast_channel_publish_cached_blob(), ast_channel_unhold_type(), AST_CONTROL_UNHOLD, ast_channel::bridge_channel, 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().

◆ ast_bridge_queue_everyone_else()

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
bridgeWhat bridge to distribute frame.
bridge_channelChannel to optionally not pass frame to. (NULL to pass to everyone)
frameFrame to pass.
Note
This is intended to be called by bridge hooks and bridge technologies.
Return values
0Frame written to at least one channel.
-1Frame written to no channels.

Definition at line 1093 of file bridge_channel.c.

1094{
1095 struct ast_bridge_channel *cur;
1096 int not_written = -1;
1097
1098 if (frame->frametype == AST_FRAME_NULL) {
1099 /* "Accept" the frame and discard it. */
1100 return 0;
1101 }
1102
1104 if (cur == bridge_channel) {
1105 continue;
1106 }
1107 if (!ast_bridge_channel_queue_frame(cur, frame)) {
1108 not_written = 0;
1109 }
1110 }
1111 return not_written;
1112}

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

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

◆ bridge_channel_attended_transfer()

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

Definition at line 1971 of file bridge_channel.c.

1973{
1974 RAII_VAR(struct ast_channel *, chan_target, NULL, ao2_cleanup);
1975 RAII_VAR(struct ast_channel *, chan_bridged, NULL, ao2_cleanup);
1976
1977 chan_target = ast_channel_get_by_name(target_chan_name);
1978 if (!chan_target) {
1979 /* Dang, it disappeared somehow */
1981 return;
1982 }
1983
1984 ast_bridge_channel_lock(bridge_channel);
1985 chan_bridged = bridge_channel->chan;
1986 ast_assert(chan_bridged != NULL);
1987 ao2_ref(chan_bridged, +1);
1988 ast_bridge_channel_unlock(bridge_channel);
1989
1992 ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
1993
1994 /* Release the ref we tried to pass to ast_bridge_set_after_callback(). */
1995 ast_channel_unref(chan_target);
1996 }
1998}
int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb callback, ast_bridge_after_cb_failed failed, void *data)
Setup an after bridge callback for when the channel leaves the bridging system.
Definition: bridge_after.c:251
static void after_bridge_move_channel_fail(enum ast_bridge_after_cb_reason reason, void *data)
static void after_bridge_move_channel(struct ast_channel *chan_bridged, void *data)
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition: channel.c:1397
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008

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

◆ bridge_channel_blind_transfer()

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

Definition at line 1960 of file bridge_channel.c.

1962{
1963 ast_async_goto(bridge_channel->chan, blind_data->context, blind_data->exten, 1);
1965}
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:6984
char exten[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]

References ast_async_goto(), ast_bridge_channel_kick(), AST_CAUSE_NORMAL_CLEARING, ast_bridge_channel::chan, blind_transfer_data::context, and blind_transfer_data::exten.

Referenced by bridge_channel_handle_action().

◆ bridge_channel_cancel_owed_events()

static void bridge_channel_cancel_owed_events ( struct ast_bridge_channel bridge_channel)
static

Definition at line 781 of file bridge_channel.c.

782{
783 bridge_channel->owed.dtmf_digit = '\0';
784 bridge_channel->owed.t38_terminate = 0;
785}
struct ast_bridge_channel::@196 owed

References ast_bridge_channel::dtmf_digit, ast_bridge_channel::owed, and ast_bridge_channel::t38_terminate.

Referenced by bridge_channel_internal_push_full().

◆ bridge_channel_destroy()

static void bridge_channel_destroy ( void *  obj)
static

Definition at line 3072 of file bridge_channel.c.

3073{
3074 struct ast_bridge_channel *bridge_channel = obj;
3075 struct ast_frame *fr;
3076
3077 if (bridge_channel->callid) {
3078 bridge_channel->callid = 0;
3079 }
3080
3081 if (bridge_channel->bridge) {
3082 ao2_ref(bridge_channel->bridge, -1);
3083 bridge_channel->bridge = NULL;
3084 }
3085
3086 /* Flush any unhandled wr_queue frames. */
3087 while ((fr = AST_LIST_REMOVE_HEAD(&bridge_channel->wr_queue, frame_list))) {
3089 }
3090 ast_alertpipe_close(bridge_channel->alert_pipe);
3091
3092 /* Flush any unhandled deferred_queue frames. */
3093 while ((fr = AST_LIST_REMOVE_HEAD(&bridge_channel->deferred_queue, frame_list))) {
3094 ast_frfree(fr);
3095 }
3096
3097 ast_cond_destroy(&bridge_channel->cond);
3098
3099 ao2_cleanup(bridge_channel->write_format);
3100 ao2_cleanup(bridge_channel->read_format);
3101
3102 AST_VECTOR_FREE(&bridge_channel->stream_map.to_bridge);
3103 AST_VECTOR_FREE(&bridge_channel->stream_map.to_channel);
3104}
void ast_alertpipe_close(int alert_pipe[2])
Close an alert pipe.
Definition: alertpipe.c:79
#define ast_frfree(fr)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define ast_cond_destroy(cond)
Definition: lock.h:209
struct ast_bridge_channel::@195 deferred_queue
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174

References ast_bridge_channel::alert_pipe, ao2_cleanup, ao2_ref, ast_alertpipe_close(), ast_cond_destroy, ast_frfree, AST_LIST_REMOVE_HEAD, AST_VECTOR_FREE, ast_bridge_channel::bridge, bridge_frame_free(), ast_bridge_channel::callid, ast_bridge_channel::cond, ast_bridge_channel::deferred_queue, NULL, ast_bridge_channel::read_format, ast_bridge_channel::stream_map, ast_bridge_channel::to_bridge, ast_bridge_channel::to_channel, ast_bridge_channel::wr_queue, and ast_bridge_channel::write_format.

Referenced by bridge_channel_internal_alloc().

◆ bridge_channel_dissolve_check()

static void bridge_channel_dissolve_check ( struct ast_bridge_channel bridge_channel)
static

Definition at line 2076 of file bridge_channel.c.

2077{
2078 struct ast_bridge *bridge = bridge_channel->bridge;
2079
2080 if (bridge->dissolved) {
2081 return;
2082 }
2083
2084 if (!bridge->num_channels
2086 /* Last channel leaving the bridge turns off the lights. */
2087 bridge_dissolve(bridge, ast_channel_hangupcause(bridge_channel->chan));
2088 return;
2089 }
2090
2091 switch (bridge_channel->state) {
2093 /* Do we need to dissolve the bridge because this channel hung up? */
2095 || (bridge_channel->features->usable
2096 && ast_test_flag(&bridge_channel->features->feature_flags,
2098 bridge_dissolve(bridge, ast_channel_hangupcause(bridge_channel->chan));
2099 return;
2100 }
2101 break;
2102 default:
2103 break;
2104 }
2105
2106 if (bridge->num_lonely && bridge->num_lonely == bridge->num_channels) {
2107 /*
2108 * This will start a chain reaction where each channel leaving
2109 * enters this function and causes the next to leave as long as
2110 * there aren't non-lonely channels in the bridge.
2111 */
2114 ast_channel_hangupcause(bridge_channel->chan));
2115 }
2116}
@ BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE
@ AST_BRIDGE_FLAG_DISSOLVE_EMPTY
@ AST_BRIDGE_FLAG_DISSOLVE_HANGUP
@ AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP
void bridge_dissolve(struct ast_bridge *bridge, int cause)
Definition: bridge.c:326
int ast_channel_hangupcause(const struct ast_channel *chan)
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
struct ast_flags feature_flags
unsigned int dissolved
Definition: bridge.h:394
unsigned int num_lonely
Definition: bridge.h:381
struct ast_flags feature_flags
Definition: bridge.h:373

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::feature_flags, ast_bridge_features::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().

◆ bridge_channel_do_callback()

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

Definition at line 1387 of file bridge_channel.c.

1388{
1390 bridge_channel_suspend(bridge_channel);
1391 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
1392 }
1393 data->callback(bridge_channel, data->payload_exists ? data->payload : NULL, data->payload_size);
1395 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
1396 bridge_channel_unsuspend(bridge_channel);
1397 }
1398}
static void bridge_channel_suspend(struct ast_bridge_channel *bridge_channel)
@ AST_BRIDGE_CHANNEL_CB_OPTION_MEDIA
ast_bridge_custom_callback_fn callback

References AST_BRIDGE_CHANNEL_CB_OPTION_MEDIA, AST_CONTROL_SRCUPDATE, ast_indicate(), ast_test_flag, bridge_channel_suspend(), bridge_channel_unsuspend(), bridge_custom_callback::callback, ast_bridge_channel::chan, NULL, bridge_custom_callback::payload, bridge_custom_callback::payload_exists, and bridge_custom_callback::payload_size.

Referenced by bridge_channel_handle_action().

◆ bridge_channel_dtmf_stream()

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

Definition at line 1870 of file bridge_channel.c.

1871{
1872 ast_debug(1, "Playing DTMF stream '%s' out to %p(%s)\n",
1873 dtmf, bridge_channel, ast_channel_name(bridge_channel->chan));
1874 ast_dtmf_stream(bridge_channel->chan, NULL, dtmf, 0, 0);
1875}
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
Send a string of DTMF digits to a channel.
Definition: main/app.c:1127

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

Referenced by bridge_channel_handle_action().

◆ bridge_channel_event_join_leave()

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

Definition at line 2800 of file bridge_channel.c.

2801{
2802 struct ast_bridge_features *features = bridge_channel->features;
2803 struct ast_bridge_hook *hook;
2804 struct ao2_iterator iter;
2805
2806 /* Run the specified hooks. */
2807 iter = ao2_iterator_init(features->other_hooks, 0);
2808 for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
2809 if (hook->type == type) {
2810 break;
2811 }
2812 }
2813 if (hook) {
2814 /* Found the first specified hook to run. */
2815 bridge_channel_suspend(bridge_channel);
2816 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
2817 do {
2818 if (hook->type == type) {
2819 hook->callback(bridge_channel, hook->hook_pvt);
2820 ao2_unlink(features->other_hooks, hook);
2821 }
2822 ao2_ref(hook, -1);
2823 } while ((hook = ao2_iterator_next(&iter)));
2824 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
2825 bridge_channel_unsuspend(bridge_channel);
2826 }
2827 ao2_iterator_destroy(&iter);
2828}
static const char type[]
Definition: chan_ooh323.c:109

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, type, and ast_bridge_hook::type.

Referenced by bridge_channel_internal_join().

◆ bridge_channel_feature_digit_add()

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

Definition at line 1660 of file bridge_channel.c.

1662{
1663 if (dtmf_len < ARRAY_LEN(bridge_channel->dtmf_hook_state.collected) - 1) {
1664 /* Add the new digit to the DTMF string so we can do our matching */
1665 bridge_channel->dtmf_hook_state.collected[dtmf_len++] = digit;
1666 bridge_channel->dtmf_hook_state.collected[dtmf_len] = '\0';
1667
1668 ast_debug(1, "DTMF feature string on %p(%s) is now '%s'\n",
1669 bridge_channel, ast_channel_name(bridge_channel->chan),
1670 bridge_channel->dtmf_hook_state.collected);
1671 }
1672
1673 return dtmf_len;
1674}

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

Referenced by ast_bridge_channel_feature_digit(), and ast_bridge_channel_feature_digit_add().

◆ bridge_channel_feature_digit_timeout()

static unsigned int bridge_channel_feature_digit_timeout ( struct ast_bridge_channel bridge_channel)
static

Definition at line 1676 of file bridge_channel.c.

1677{
1678 unsigned int digit_timeout;
1679 struct ast_features_general_config *gen_cfg;
1680
1681 /* Determine interdigit timeout */
1682 ast_channel_lock(bridge_channel->chan);
1683 gen_cfg = ast_get_chan_features_general_config(bridge_channel->chan);
1684 ast_channel_unlock(bridge_channel->chan);
1685
1686 if (!gen_cfg) {
1687 ast_log(LOG_ERROR, "Unable to retrieve features configuration.\n");
1688 return 3000; /* Pick a reasonable failsafe timeout in ms */
1689 }
1690
1691 digit_timeout = gen_cfg->featuredigittimeout;
1692 ao2_ref(gen_cfg, -1);
1693
1694 return digit_timeout;
1695}
struct ast_features_general_config * ast_get_chan_features_general_config(struct ast_channel *chan)
Get the general configuration options for a channel.
General features configuration items.

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

◆ bridge_channel_feature_timeout()

static int bridge_channel_feature_timeout ( struct ast_bridge_channel bridge_channel)
static

Definition at line 2685 of file bridge_channel.c.

2686{
2687 int ms;
2688
2689 if (bridge_channel->dtmf_hook_state.collected[0]) {
2691 ast_tvnow());
2692 if (ms < 0) {
2693 /* Expire immediately. */
2694 ms = 0;
2695 }
2696 } else {
2697 /* Timer is not active so wait forever. */
2698 ms = -1;
2699 }
2700
2701 return ms;
2702}
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107

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

◆ bridge_channel_handle_action()

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

Definition at line 2009 of file bridge_channel.c.

2011{
2012 switch (action) {
2014 bridge_channel_suspend(bridge_channel);
2015 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
2016 bridge_channel_dtmf_stream(bridge_channel, data);
2017 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
2018 bridge_channel_unsuspend(bridge_channel);
2019 break;
2022 bridge_channel_talking(bridge_channel,
2024 break;
2026 bridge_channel_suspend(bridge_channel);
2027 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
2028 bridge_channel_playfile(bridge_channel, data);
2029 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
2030 bridge_channel_unsuspend(bridge_channel);
2031 break;
2033 bridge_channel_suspend(bridge_channel);
2034 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
2035 bridge_channel_run_app(bridge_channel, data);
2036 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
2037 bridge_channel_unsuspend(bridge_channel);
2038 break;
2040 bridge_channel_do_callback(bridge_channel, data);
2041 break;
2043 bridge_channel_suspend(bridge_channel);
2044 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
2045 bridge_channel_park(bridge_channel, data);
2046 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
2047 bridge_channel_unsuspend(bridge_channel);
2048 break;
2050 bridge_channel_blind_transfer(bridge_channel, data);
2051 break;
2053 bridge_channel_attended_transfer(bridge_channel, data);
2054 break;
2055 default:
2056 break;
2057 }
2058
2059 /* While invoking an action it is possible for the channel to be hung up. So
2060 * that the bridge respects this we check here and if hung up kick it out.
2061 */
2062 if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) {
2063 ast_bridge_channel_kick(bridge_channel, 0);
2064 }
2065}
static void bridge_channel_run_app(struct ast_bridge_channel *bridge_channel, struct bridge_run_app *data)
static void bridge_channel_attended_transfer(struct ast_bridge_channel *bridge_channel, const char *target_chan_name)
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)
static void bridge_channel_blind_transfer(struct ast_bridge_channel *bridge_channel, struct blind_transfer_data *blind_data)
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_talking(struct ast_bridge_channel *bridge_channel, int talking)
@ BRIDGE_CHANNEL_ACTION_ATTENDED_TRANSFER
@ BRIDGE_CHANNEL_ACTION_DTMF_STREAM
@ BRIDGE_CHANNEL_ACTION_PLAY_FILE
@ BRIDGE_CHANNEL_ACTION_BLIND_TRANSFER
@ BRIDGE_CHANNEL_ACTION_CALLBACK
@ BRIDGE_CHANNEL_ACTION_RUN_APP
@ BRIDGE_CHANNEL_ACTION_PARK

References ast_control_read_action_payload::action, ast_bridge_channel_kick(), ast_check_hangup_locked(), 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().

◆ bridge_channel_handle_control()

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

Definition at line 2268 of file bridge_channel.c.

2269{
2270 struct ast_channel *chan;
2271 struct ast_option_header *aoh;
2272
2273 chan = bridge_channel->chan;
2274 switch (fr->subclass.integer) {
2276 if (ast_channel_redirecting_sub(NULL, chan, fr, 1)) {
2277 ast_indicate_data(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);
2278 }
2279 break;
2281 if (ast_channel_connected_line_sub(NULL, chan, fr, 1)) {
2282 ast_indicate_data(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);
2283 }
2284 break;
2285 case AST_CONTROL_OPTION:
2286 /*
2287 * Forward option Requests, but only ones we know are safe These
2288 * are ONLY sent by chan_iax2 and I'm not convinced that they
2289 * are useful. I haven't deleted them entirely because I just am
2290 * not sure of the ramifications of removing them.
2291 */
2292 aoh = fr->data.ptr;
2293 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
2294 switch (ntohs(aoh->option)) {
2296 case AST_OPTION_TDD:
2301 ast_channel_setoption(chan, ntohs(aoh->option), aoh->data,
2302 fr->datalen - sizeof(*aoh), 0);
2303 break;
2304 default:
2305 break;
2306 }
2307 }
2308 break;
2309 case AST_CONTROL_ANSWER:
2310 if (ast_channel_state(chan) != AST_STATE_UP) {
2311 ast_answer(chan);
2312 ast_bridge_channel_lock_bridge(bridge_channel);
2313 bridge_channel->bridge->reconfigured = 1;
2314 bridge_reconfigured(bridge_channel->bridge, 0);
2315 ast_bridge_unlock(bridge_channel->bridge);
2316 } else {
2317 ast_indicate(chan, -1);
2318 }
2319 break;
2321 /* Should never happen. */
2322 ast_assert(0);
2323 break;
2325 ast_indicate_data(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);
2326 break;
2327 default:
2328 ast_indicate_data(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);
2329 break;
2330 }
2331}
void bridge_reconfigured(struct ast_bridge *bridge, unsigned int colp_update)
Definition: bridge.c:1472
int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *connected_info, int frame)
Run a connected line interception subroutine and update a channel's connected line information.
Definition: channel.c:10343
int ast_channel_redirecting_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *redirecting_info, int is_frame)
Run a redirecting interception subroutine and update a channel's redirecting information.
Definition: channel.c:10388
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4612
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7395
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2774
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
#define AST_OPTION_RELAXDTMF
#define AST_OPTION_TONE_VERIFY
#define AST_OPTION_DIGIT_DETECT
#define AST_OPTION_TDD
#define AST_OPTION_FLAG_REQUEST
#define AST_OPTION_FAX_DETECT
@ AST_CONTROL_REDIRECTING
@ AST_CONTROL_ANSWER
@ AST_CONTROL_OPTION
@ AST_CONTROL_STREAM_TOPOLOGY_CHANGED
@ AST_CONTROL_CONNECTED_LINE
@ AST_CONTROL_MASQUERADE_NOTIFY
#define AST_OPTION_AUDIO_MODE
unsigned int reconfigured
Definition: bridge.h:392
struct ast_frame_subclass subclass

References ast_answer(), ast_assert, ast_bridge_channel_lock_bridge(), ast_bridge_unlock, ast_channel_connected_line_sub(), 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_CONTROL_STREAM_TOPOLOGY_CHANGED, 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_bridge_channel::bridge, bridge_reconfigured(), ast_bridge_channel::chan, ast_frame::data, ast_option_header::data, ast_frame::datalen, ast_frame_subclass::integer, NULL, ast_frame::ptr, ast_bridge::reconfigured, and ast_frame::subclass.

Referenced by bridge_channel_handle_write().

◆ bridge_channel_handle_feature_timeout()

static void bridge_channel_handle_feature_timeout ( struct ast_bridge_channel bridge_channel)
static

Definition at line 1824 of file bridge_channel.c.

1825{
1826 if (!bridge_channel->dtmf_hook_state.collected[0]
1827 || 0 < ast_tvdiff_ms(bridge_channel->dtmf_hook_state.interdigit_timeout,
1828 ast_tvnow())) {
1829 /* Not within a sequence or not timed out. */
1830 return;
1831 }
1832
1833 ast_bridge_channel_feature_digit(bridge_channel, 0);
1834}
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.

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

◆ bridge_channel_handle_interval()

static void bridge_channel_handle_interval ( struct ast_bridge_channel bridge_channel)
static

Definition at line 1515 of file bridge_channel.c.

1516{
1517 struct ast_heap *interval_hooks;
1518 struct ast_bridge_hook_timer *hook;
1519 struct timeval start;
1520 int chan_suspended = 0;
1521
1522 interval_hooks = bridge_channel->features->interval_hooks;
1523 ast_heap_wrlock(interval_hooks);
1524 start = ast_tvnow();
1525 while ((hook = ast_heap_peek(interval_hooks, 1))) {
1526 int interval;
1527 unsigned int execution_time;
1528
1529 if (ast_tvdiff_ms(hook->timer.trip_time, start) > 0) {
1530 ast_debug(1, "Hook %p on %p(%s) wants to happen in the future, stopping our traversal\n",
1531 hook, bridge_channel, ast_channel_name(bridge_channel->chan));
1532 break;
1533 }
1534 ao2_ref(hook, +1);
1535 ast_heap_unlock(interval_hooks);
1536
1537 if (!chan_suspended
1539 chan_suspended = 1;
1540 bridge_channel_suspend(bridge_channel);
1541 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
1542 }
1543
1544 ast_debug(1, "Executing hook %p on %p(%s)\n",
1545 hook, bridge_channel, ast_channel_name(bridge_channel->chan));
1546 interval = hook->generic.callback(bridge_channel, hook->generic.hook_pvt);
1547
1548 ast_heap_wrlock(interval_hooks);
1549 if (ast_heap_peek(interval_hooks, hook->timer.heap_index) != hook
1550 || !ast_heap_remove(interval_hooks, hook)) {
1551 /* Interval hook is already removed from the bridge_channel. */
1552 ao2_ref(hook, -1);
1553 continue;
1554 }
1555 ao2_ref(hook, -1);
1556
1557 if (interval < 0) {
1558 ast_debug(1, "Removed interval hook %p from %p(%s)\n",
1559 hook, bridge_channel, ast_channel_name(bridge_channel->chan));
1560 ao2_ref(hook, -1);
1561 continue;
1562 }
1563 if (interval) {
1564 /* Set new interval for the hook. */
1565 hook->timer.interval = interval;
1566 }
1567
1568 ast_debug(1, "Updating interval hook %p with interval %u on %p(%s)\n",
1569 hook, hook->timer.interval, bridge_channel,
1570 ast_channel_name(bridge_channel->chan));
1571
1572 /* resetting start */
1573 start = ast_tvnow();
1574
1575 /*
1576 * Resetup the interval hook for the next interval. We may need
1577 * to skip over any missed intervals because the hook was
1578 * delayed or took too long.
1579 */
1580 execution_time = ast_tvdiff_ms(start, hook->timer.trip_time);
1581 while (hook->timer.interval < execution_time) {
1582 execution_time -= hook->timer.interval;
1583 }
1584 hook->timer.trip_time = ast_tvadd(start, ast_samp2tv(hook->timer.interval - execution_time, 1000));
1585 hook->timer.seqno = ast_atomic_fetchadd_int((int *) &bridge_channel->features->interval_sequence, +1);
1586
1587 if (ast_heap_push(interval_hooks, hook)) {
1588 /* Could not push the hook back onto the heap. */
1589 ao2_ref(hook, -1);
1590 }
1591 }
1592 ast_heap_unlock(interval_hooks);
1593
1594 if (chan_suspended) {
1595 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
1596 bridge_channel_unsuspend(bridge_channel);
1597 }
1598}
@ AST_BRIDGE_HOOK_TIMER_OPTION_MEDIA
#define ast_heap_unlock(h)
Definition: heap.h:249
void * ast_heap_remove(struct ast_heap *h, void *elm)
Remove a specific element from a heap.
Definition: heap.c:251
#define ast_heap_push(h, elm)
Push an element on to a heap.
Definition: heap.h:125
#define ast_heap_wrlock(h)
Definition: heap.h:247
void * ast_heap_peek(struct ast_heap *h, unsigned int index)
Peek at an element on a heap.
Definition: heap.c:267
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:764
unsigned int interval_sequence
struct ast_heap * interval_hooks
struct ast_bridge_hook generic
struct ast_bridge_hook_timer_parms timer
Definition: heap.c:36

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

◆ bridge_channel_handle_write()

static void bridge_channel_handle_write ( struct ast_bridge_channel bridge_channel)
static

Definition at line 2373 of file bridge_channel.c.

2374{
2375 struct ast_frame *fr;
2376 struct sync_payload *sync_payload;
2377 int num;
2378 struct ast_msg_data *msg;
2379
2380 ast_bridge_channel_lock(bridge_channel);
2381
2382 /* It's not good to have unbalanced frames and alert_pipe alerts. */
2383 ast_assert(!AST_LIST_EMPTY(&bridge_channel->wr_queue));
2384 if (AST_LIST_EMPTY(&bridge_channel->wr_queue)) {
2385 /* No frame, flush the alert pipe of excess alerts. */
2386 ast_log(LOG_WARNING, "Weird. No frame from bridge for %s to process?\n",
2387 ast_channel_name(bridge_channel->chan));
2388 ast_alertpipe_read(bridge_channel->alert_pipe);
2389 ast_bridge_channel_unlock(bridge_channel);
2390 return;
2391 }
2392
2393 AST_LIST_TRAVERSE_SAFE_BEGIN(&bridge_channel->wr_queue, fr, frame_list) {
2394 if (bridge_channel->dtmf_hook_state.collected[0]) {
2395 switch (fr->frametype) {
2398 /* Defer processing these frames while DTMF is collected. */
2399 continue;
2400 default:
2401 break;
2402 }
2403 }
2404 ast_alertpipe_read(bridge_channel->alert_pipe);
2406 break;
2407 }
2409
2410 ast_bridge_channel_unlock(bridge_channel);
2411
2412 if (!fr) {
2413 /*
2414 * Wait some to reduce CPU usage from a tight loop
2415 * without any wait because we only have deferred
2416 * frames in the wr_queue.
2417 */
2418 usleep(1);
2419 return;
2420 }
2421
2422 switch (fr->frametype) {
2424 bridge_channel_handle_action(bridge_channel, fr->subclass.integer, fr->data.ptr);
2425 break;
2427 sync_payload = fr->data.ptr;
2429 break;
2430 case AST_FRAME_CONTROL:
2431 bridge_channel_handle_control(bridge_channel, fr);
2432 break;
2433 case AST_FRAME_NULL:
2434 break;
2435 case AST_FRAME_TEXT:
2436 ast_debug(1, "Sending TEXT frame to '%s': %*.s\n",
2437 ast_channel_name(bridge_channel->chan), fr->datalen, (char *)fr->data.ptr);
2438 sendtext_safe(bridge_channel->chan, fr);
2439 break;
2441 msg = (struct ast_msg_data *)fr->data.ptr;
2442 ast_debug(1, "Sending TEXT_DATA frame from '%s' to '%s:%s': %s\n",
2445 ast_channel_name(bridge_channel->chan),
2447 ast_sendtext_data(bridge_channel->chan, msg);
2448 break;
2449 default:
2450 /* Assume that there is no mapped stream for this */
2451 num = -1;
2452
2453 if (fr->stream_num > -1) {
2454 ast_bridge_channel_lock(bridge_channel);
2455 if (fr->stream_num < (int)AST_VECTOR_SIZE(&bridge_channel->stream_map.to_channel)) {
2456 num = AST_VECTOR_GET(&bridge_channel->stream_map.to_channel, fr->stream_num);
2457 }
2458 ast_bridge_channel_unlock(bridge_channel);
2459
2460 /* If there is no mapped stream after checking the mapping then there is nowhere
2461 * to write this frame to, so drop it.
2462 */
2463 if (num == -1) {
2464 break;
2465 }
2466 }
2467
2468 /* Write the frame to the channel. */
2469 bridge_channel->activity = BRIDGE_CHANNEL_THREAD_SIMPLE;
2470 ast_write_stream(bridge_channel->chan, num, fr);
2471 break;
2472 }
2474}
ast_alert_status_t ast_alertpipe_read(int alert_pipe[2])
Read an event from an alert pipe.
Definition: alertpipe.c:102
static void sendtext_safe(struct ast_channel *chan, const struct ast_frame *f)
static void bridge_channel_handle_control(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr)
static void bridge_channel_handle_action(struct ast_bridge_channel *bridge_channel, enum bridge_channel_action_type action, void *data)
@ BRIDGE_CHANNEL_THREAD_SIMPLE
int ast_sendtext_data(struct ast_channel *chan, struct ast_msg_data *msg)
Sends text to a channel in an ast_msg_data structure wrapper with ast_sendtext as fallback.
Definition: channel.c:4710
int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame *frame)
Write a frame to a stream This function writes the given frame to the indicated stream on the channel...
Definition: channel.c:5108
@ AST_FRAME_BRIDGE_ACTION_SYNC
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
enum bridge_channel_thread_state activity
The bridge channel thread activity.
Frame payload for synchronous bridge actions.
unsigned char data[0]

References ast_bridge_channel::activity, ast_bridge_channel::alert_pipe, ast_alertpipe_read(), ast_assert, ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_channel_name(), ast_debug, AST_FRAME_BRIDGE_ACTION, AST_FRAME_BRIDGE_ACTION_SYNC, AST_FRAME_CONTROL, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_TEXT_DATA, AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, AST_MSG_DATA_ATTR_BODY, AST_MSG_DATA_ATTR_FROM, AST_MSG_DATA_ATTR_TO, ast_msg_data_get_attribute(), ast_sendtext_data(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_write_stream(), bridge_channel_handle_action(), bridge_channel_handle_control(), BRIDGE_CHANNEL_THREAD_SIMPLE, bridge_frame_free(), ast_bridge_channel::chan, ast_bridge_channel::collected, ast_frame::data, sync_payload::data, ast_frame::datalen, ast_bridge_channel::dtmf_hook_state, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, ast_frame::ptr, sendtext_safe(), ast_bridge_channel::stream_map, ast_frame::stream_num, ast_frame::subclass, ast_bridge_channel::to_channel, and ast_bridge_channel::wr_queue.

Referenced by bridge_channel_wait().

◆ bridge_channel_internal_alloc()

struct ast_bridge_channel * bridge_channel_internal_alloc ( struct ast_bridge bridge)

Definition at line 3106 of file bridge_channel.c.

3107{
3108 struct ast_bridge_channel *bridge_channel;
3109
3110 bridge_channel = ao2_alloc(sizeof(struct ast_bridge_channel), bridge_channel_destroy);
3111 if (!bridge_channel) {
3112 return NULL;
3113 }
3114 ast_cond_init(&bridge_channel->cond, NULL);
3115 if (ast_alertpipe_init(bridge_channel->alert_pipe)) {
3116 ao2_ref(bridge_channel, -1);
3117 return NULL;
3118 }
3119 if (bridge) {
3120 bridge_channel->bridge = bridge;
3121 ao2_ref(bridge_channel->bridge, +1);
3122 }
3123
3124 /* The stream_map is initialized later - see ast_bridge_channel_stream_map */
3125
3126 return bridge_channel;
3127}
int ast_alertpipe_init(int alert_pipe[2])
Initialize an alert pipe.
Definition: alertpipe.c:38
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
static void bridge_channel_destroy(void *obj)
#define ast_cond_init(cond, attr)
Definition: lock.h:208

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

Referenced by ast_bridge_join(), and bridge_impart_internal().

◆ bridge_channel_internal_allows_optimization()

int bridge_channel_internal_allows_optimization ( struct ast_bridge_channel bridge_channel)

Definition at line 3065 of file bridge_channel.c.

3066{
3067 return bridge_channel->in_bridge
3068 && AST_LIST_EMPTY(&bridge_channel->wr_queue);
3069}

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

◆ bridge_channel_internal_join()

int bridge_channel_internal_join ( struct ast_bridge_channel bridge_channel)

Definition at line 2830 of file bridge_channel.c.

2831{
2832 int res = 0;
2833 uint8_t indicate_src_change = 0;
2834 struct ast_bridge_features *channel_features;
2835 struct ast_channel *peer;
2836 struct ast_channel *swap;
2837
2838 ast_debug(1, "Bridge %s: %p(%s) is joining\n",
2841
2842 /*
2843 * Directly locking the bridge is safe here because nobody else
2844 * knows about this bridge_channel yet.
2845 */
2847
2850
2851 if (peer) {
2852 struct ast_bridge *peer_bridge;
2853
2854 ast_channel_unlock(bridge_channel->chan);
2855
2856 ast_channel_lock(peer);
2857 peer_bridge = ast_channel_internal_bridge(peer);
2858 ast_channel_unlock(peer);
2859 ast_channel_unref(peer);
2860
2861 /* As we are only doing a pointer comparison we don't need the peer_bridge
2862 * to be reference counted or locked.
2863 */
2864 if (peer_bridge == bridge_channel->bridge) {
2865 ast_bridge_unlock(bridge_channel->bridge);
2866 ast_debug(1, "Bridge %s: %p(%s) denying Bridge join to prevent Local channel loop\n",
2867 bridge_channel->bridge->uniqueid,
2868 bridge_channel,
2869 ast_channel_name(bridge_channel->chan));
2870 return -1;
2871 }
2872
2873 ast_channel_lock(bridge_channel->chan);
2874 }
2875
2876 bridge_channel->read_format = ao2_bump(ast_channel_readformat(bridge_channel->chan));
2877 bridge_channel->write_format = ao2_bump(ast_channel_writeformat(bridge_channel->chan));
2878
2879 /* Make sure we're still good to be put into a bridge */
2880 if (ast_channel_internal_bridge(bridge_channel->chan)
2881 || ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_ZOMBIE)) {
2882 ast_channel_unlock(bridge_channel->chan);
2883 ast_bridge_unlock(bridge_channel->bridge);
2884 ast_debug(1, "Bridge %s: %p(%s) failed to join Bridge\n",
2885 bridge_channel->bridge->uniqueid,
2886 bridge_channel,
2887 ast_channel_name(bridge_channel->chan));
2888 return -1;
2889 }
2890 ast_channel_internal_bridge_set(bridge_channel->chan, bridge_channel->bridge);
2891
2892 /* Attach features requested by the channel */
2893 channel_features = ast_channel_feature_hooks_get(bridge_channel->chan);
2894 if (channel_features) {
2895 ast_bridge_features_merge(bridge_channel->features, channel_features);
2896 }
2897 ast_channel_unlock(bridge_channel->chan);
2898
2899 /* Add the jitterbuffer if the channel requires it */
2900 ast_jb_enable_for_channel(bridge_channel->chan);
2901
2902 if (!bridge_channel->bridge->callid) {
2903 bridge_channel->bridge->callid = ast_read_threadstorage_callid();
2904 }
2905
2906 /* Take the swap channel ref from the bridge_channel struct. */
2907 swap = bridge_channel->swap;
2908
2909 if (bridge_channel_internal_push(bridge_channel)) {
2910 int cause = bridge_channel->bridge->cause;
2911
2912 ast_bridge_unlock(bridge_channel->bridge);
2913 ast_bridge_channel_kick(bridge_channel, cause);
2914 ast_bridge_channel_lock_bridge(bridge_channel);
2915 ast_bridge_features_remove(bridge_channel->features,
2917 bridge_channel_dissolve_check(bridge_channel);
2918 res = -1;
2919 }
2920 bridge_reconfigured(bridge_channel->bridge, !bridge_channel->inhibit_colp);
2921
2922 if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
2923 /*
2924 * Indicate a source change since this channel is entering the
2925 * bridge system only if the bridge technology is not MULTIMIX
2926 * capable. The MULTIMIX technology has already done it.
2927 */
2928 if (!(bridge_channel->bridge->technology->capabilities
2930 indicate_src_change = 1;
2931 }
2932
2933 bridge_channel_impart_signal(bridge_channel->chan);
2934 ast_bridge_unlock(bridge_channel->bridge);
2935
2936 /* Must release any swap ref after unlocking the bridge. */
2937 ao2_t_cleanup(swap, "Bridge push with swap successful");
2938 swap = NULL;
2939
2940 if (indicate_src_change) {
2941 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCCHANGE);
2942 }
2943
2945
2946 while (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
2947 /* Wait for something to do. */
2948 bridge_channel_wait(bridge_channel);
2949 }
2950
2951 /* Force a timeout on any accumulated DTMF hook digits. */
2952 ast_bridge_channel_feature_digit(bridge_channel, 0);
2953
2955 ast_bridge_channel_lock_bridge(bridge_channel);
2956 }
2957
2958 bridge_channel_internal_pull(bridge_channel);
2959 bridge_channel_settle_owed_events(bridge_channel->bridge, bridge_channel);
2960 bridge_reconfigured(bridge_channel->bridge, 1);
2961
2962 /* Remove ourselves if we are the video source */
2963 ast_bridge_remove_video_src(bridge_channel->bridge, bridge_channel->chan);
2964
2965 ast_bridge_unlock(bridge_channel->bridge);
2966
2967 /* Must release any swap ref after unlocking the bridge. */
2968 ao2_t_cleanup(swap, "Bridge push with swap failed or exited immediately");
2969
2970 /* Complete any active hold before exiting the bridge. */
2971 if (ast_channel_hold_state(bridge_channel->chan) == AST_CONTROL_HOLD) {
2972 ast_debug(1, "Channel %s simulating UNHOLD for bridge end.\n",
2973 ast_channel_name(bridge_channel->chan));
2974 ast_indicate(bridge_channel->chan, AST_CONTROL_UNHOLD);
2975 }
2976
2977 /* Complete any partial DTMF digit before exiting the bridge. */
2978 if (ast_channel_sending_dtmf_digit(bridge_channel->chan)) {
2979 ast_channel_end_dtmf(bridge_channel->chan,
2980 ast_channel_sending_dtmf_digit(bridge_channel->chan),
2981 ast_channel_sending_dtmf_tv(bridge_channel->chan), "bridge end");
2982 }
2983
2984 /* Complete any T.38 session before exiting the bridge. */
2985 if (ast_channel_is_t38_active(bridge_channel->chan)) {
2986 struct ast_control_t38_parameters t38_parameters = {
2988 };
2989
2990 ast_debug(1, "Channel %s simulating T.38 terminate for bridge end.\n",
2991 ast_channel_name(bridge_channel->chan));
2993 &t38_parameters, sizeof(t38_parameters));
2994 }
2995
2996 /* Indicate a source change since this channel is leaving the bridge system. */
2997 ast_indicate(bridge_channel->chan, AST_CONTROL_SRCCHANGE);
2998
2999 /*
3000 * Wait for any dual redirect to complete.
3001 *
3002 * Must be done while "still in the bridge" for ast_async_goto()
3003 * to work right.
3004 */
3006 sched_yield();
3007 }
3008 ast_channel_lock(bridge_channel->chan);
3009 ast_channel_internal_bridge_set(bridge_channel->chan, NULL);
3010 ast_channel_unlock(bridge_channel->chan);
3011
3012 ast_bridge_channel_restore_formats(bridge_channel);
3013
3014 return res;
3015}
void ast_jb_enable_for_channel(struct ast_channel *chan)
Sets a jitterbuffer frame hook on the channel based on the channel's stored jitterbuffer configuratio...
Definition: abstract_jb.c:585
#define ao2_t_cleanup(obj, tag)
Definition: astobj2.h:1935
void ast_bridge_features_remove(struct ast_bridge_features *features, enum ast_bridge_hook_remove_flags flags)
Remove marked bridge channel feature hooks.
Definition: bridge.c:3570
@ AST_BRIDGE_CAPABILITY_MULTIMIX
Definition: bridge.h:98
void ast_bridge_remove_video_src(struct ast_bridge *bridge, struct ast_channel *chan)
remove a channel as a source of video for the bridge.
Definition: bridge.c:3986
void bridge_channel_settle_owed_events(struct ast_bridge *orig_bridge, struct ast_bridge_channel *bridge_channel)
static void bridge_channel_wait(struct ast_bridge_channel *bridge_channel)
int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel)
static void bridge_channel_dissolve_check(struct ast_bridge_channel *bridge_channel)
static void bridge_channel_event_join_leave(struct ast_bridge_channel *bridge_channel, enum ast_bridge_hook_type type)
void bridge_channel_internal_pull(struct ast_bridge_channel *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_joi...
void bridge_channel_impart_signal(struct ast_channel *chan)
Definition: bridge.c:1651
@ AST_BRIDGE_HOOK_TYPE_JOIN
@ AST_BRIDGE_HOOK_TYPE_LEAVE
@ AST_BRIDGE_HOOK_REMOVE_ON_PULL
void ast_bridge_features_merge(struct ast_bridge_features *into, const struct ast_bridge_features *from)
Merge one ast_bridge_features into another.
Definition: bridge.c:3664
struct ast_bridge * ast_channel_internal_bridge(const struct ast_channel *chan)
void ast_channel_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why)
Simulate a DTMF end on a broken bridge channel.
Definition: channel.c:10874
struct timeval ast_channel_sending_dtmf_tv(const struct ast_channel *chan)
struct ast_bridge_features * ast_channel_feature_hooks_get(struct ast_channel *chan)
Gets the channel-attached features a channel has access to upon being bridged.
Definition: channel.c:10908
void ast_channel_internal_bridge_set(struct ast_channel *chan, struct ast_bridge *value)
@ AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT
Definition: channel.h:1055
@ AST_FLAG_ZOMBIE
Definition: channel.h:1007
int ast_channel_hold_state(const struct ast_channel *chan)
char ast_channel_sending_dtmf_digit(const struct ast_channel *chan)
int ast_channel_is_t38_active(struct ast_channel *chan)
This function will check if T.38 is active on the channel.
struct ast_channel * ast_local_get_peer(struct ast_channel *ast)
Get the other local channel in the pair.
Definition: core_local.c:288
@ AST_T38_TERMINATED
@ AST_CONTROL_T38_PARAMETERS
@ AST_CONTROL_SRCCHANGE
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:2273
struct ast_channel * swap
unsigned int inhibit_colp
ast_callid callid
Definition: bridge.h:365
const ast_string_field uniqueid
Definition: bridge.h:405
int cause
Definition: bridge.h:390
struct ast_bridge_technology * technology
Definition: bridge.h:359
enum ast_control_t38 request_response

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_remove_video_src(), 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_is_t38_active(), ast_channel_lock, ast_channel_name(), ast_channel_readformat(), ast_channel_sending_dtmf_digit(), ast_channel_sending_dtmf_tv(), ast_channel_unlock, ast_channel_unref, ast_channel_writeformat(), AST_CONTROL_HOLD, AST_CONTROL_SRCCHANGE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_UNHOLD, ast_debug, AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT, AST_FLAG_ZOMBIE, ast_indicate(), ast_indicate_data(), ast_jb_enable_for_channel(), ast_local_get_peer(), ast_read_threadstorage_callid(), AST_T38_TERMINATED, ast_test_flag, ast_bridge_channel::bridge, ast_channel::bridge_channel, bridge_channel_dissolve_check(), bridge_channel_event_join_leave(), bridge_channel_impart_signal(), 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_control_t38_parameters::request_response, 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().

◆ bridge_channel_internal_pull()

void bridge_channel_internal_pull ( struct ast_bridge_channel bridge_channel)

Definition at line 2118 of file bridge_channel.c.

2119{
2120 struct ast_bridge *bridge = bridge_channel->bridge;
2121
2122 if (!bridge_channel->in_bridge) {
2123 return;
2124 }
2125 bridge_channel->in_bridge = 0;
2126
2127 ast_debug(1, "Bridge %s: pulling %p(%s)\n",
2128 bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
2129
2130 ast_verb(3, "Channel %s left '%s' %s-bridge <%s>\n",
2131 ast_channel_name(bridge_channel->chan),
2132 bridge->technology->name,
2133 bridge->v_table->name,
2134 bridge->uniqueid);
2135
2136 if (!bridge_channel->just_joined) {
2137 /* Tell the bridge technology we are leaving so they tear us down */
2138 ast_debug(1, "Bridge %s: %p(%s) is leaving %s technology\n",
2139 bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
2140 bridge->technology->name);
2141 if (bridge->technology->leave) {
2142 bridge->technology->leave(bridge, bridge_channel);
2143 }
2144 }
2145
2146 /* Remove channel from the bridge */
2147 if (!bridge_channel->suspended) {
2148 --bridge->num_active;
2149 }
2151 --bridge->num_lonely;
2152 }
2153 --bridge->num_channels;
2154 AST_LIST_REMOVE(&bridge->channels, bridge_channel, entry);
2155
2156 bridge_channel_dissolve_check(bridge_channel);
2157 bridge->v_table->pull(bridge, bridge_channel);
2158
2159 ast_bridge_channel_clear_roles(bridge_channel);
2160
2161 /* If we are not going to be hung up after leaving a bridge, and we were an
2162 * outgoing channel, clear the outgoing flag.
2163 */
2165 && (ast_channel_is_leaving_bridge(bridge_channel->chan)
2166 || bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT)) {
2167 ast_debug(2, "Channel %s will survive this bridge; clearing outgoing (dialed) flag\n", ast_channel_name(bridge_channel->chan));
2169 }
2170
2171 bridge->reconfigured = 1;
2172 ast_bridge_publish_leave(bridge, bridge_channel->chan);
2173}
@ AST_BRIDGE_CHANNEL_FLAG_LONELY
void ast_bridge_channel_clear_roles(struct ast_bridge_channel *bridge_channel)
Clear all roles from a bridge_channel's role list.
Definition: bridge_roles.c:491
void ast_channel_clear_flag(struct ast_channel *chan, unsigned int flag)
Clear a flag on a channel.
Definition: channel.c:11039
@ AST_FLAG_OUTGOING
Definition: channel.h:1019
int ast_channel_is_leaving_bridge(struct ast_channel *chan)
Determine if a channel is leaving a bridge, but not hung up.
Definition: channel.c:10555
#define ast_verb(level,...)
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856
void ast_bridge_publish_leave(struct ast_bridge *bridge, struct ast_channel *chan)
Publish a bridge channel leave event.
unsigned int just_joined
const char * name
Definition: bridge.h:263
ast_bridge_pull_channel_fn pull
Definition: bridge.h:271
void(* leave)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Remove a channel from a bridging technology instance for a bridge.
const struct ast_bridge_methods * v_table
Definition: bridge.h:355
unsigned int num_active
Definition: bridge.h:379

References ast_bridge_channel_clear_roles(), AST_BRIDGE_CHANNEL_FLAG_LONELY, ast_bridge_publish_leave(), ast_channel_clear_flag(), ast_channel_flags(), ast_channel_is_leaving_bridge(), ast_channel_name(), 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_full(), bridge_do_merge(), and bridge_do_move().

◆ bridge_channel_internal_push()

int bridge_channel_internal_push ( struct ast_bridge_channel bridge_channel)

Definition at line 2255 of file bridge_channel.c.

2256{
2257 return bridge_channel_internal_push_full(bridge_channel, 0);
2258}
int bridge_channel_internal_push_full(struct ast_bridge_channel *bridge_channel, int optimized)

References bridge_channel_internal_push_full().

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

◆ bridge_channel_internal_push_full()

int bridge_channel_internal_push_full ( struct ast_bridge_channel bridge_channel,
int  optimized 
)

Definition at line 2175 of file bridge_channel.c.

2176{
2177 struct ast_bridge *bridge = bridge_channel->bridge;
2178 struct ast_bridge_channel *swap;
2179
2180 ast_assert(!bridge_channel->in_bridge);
2181
2182 swap = bridge_find_channel(bridge, bridge_channel->swap);
2183 bridge_channel->swap = NULL;
2184
2185 if (swap) {
2186 ast_debug(1, "Bridge %s: pushing %p(%s) by swapping with %p(%s)\n",
2187 bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
2188 swap, ast_channel_name(swap->chan));
2189 } else {
2190 ast_debug(1, "Bridge %s: pushing %p(%s)\n",
2191 bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
2192 }
2193
2194 /* Add channel to the bridge */
2195 if (bridge->dissolved
2196 || bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT
2198 || bridge->v_table->push(bridge, bridge_channel, swap)) {
2199 ast_debug(1, "Bridge %s: pushing %p(%s) into bridge failed\n",
2200 bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
2201 return -1;
2202 }
2203
2204 ast_bridge_channel_establish_roles(bridge_channel);
2205
2206 if (swap) {
2208
2209 /* This flag is cleared so the act of this channel leaving does not cause it to dissolve if need be */
2211
2212 if (optimized) {
2214 }
2217
2219 }
2220
2221 bridge_channel->in_bridge = 1;
2222 bridge_channel->just_joined = 1;
2223 AST_LIST_INSERT_TAIL(&bridge->channels, bridge_channel, entry);
2226 ++bridge->num_lonely;
2227 }
2228 if (!bridge_channel->suspended) {
2229 ++bridge->num_active;
2230 }
2231
2232 ast_verb(3, "Channel %s %s%s%s '%s' %s-bridge <%s>\n",
2233 ast_channel_name(bridge_channel->chan),
2234 swap ? "swapped with " : "joined",
2235 swap ? ast_channel_name(swap->chan) : "",
2236 swap ? " into" : "",
2239 bridge->uniqueid);
2240
2241 ast_bridge_publish_enter(bridge, bridge_channel->chan, swap ? swap->chan : NULL);
2242
2243 /* Clear any BLINDTRANSFER,ATTENDEDTRANSFER and FORWARDERNAME since the transfer has completed. */
2244 pbx_builtin_setvar_helper(bridge_channel->chan, "BLINDTRANSFER", NULL);
2245 pbx_builtin_setvar_helper(bridge_channel->chan, "ATTENDEDTRANSFER", NULL);
2246 pbx_builtin_setvar_helper(bridge_channel->chan, "FORWARDERNAME", NULL);
2247
2248 /* Wake up the bridge channel thread to reevaluate any interval timers. */
2249 ast_queue_frame(bridge_channel->chan, &ast_null_frame);
2250
2251 bridge->reconfigured = 1;
2252 return 0;
2253}
static void bridge_channel_cancel_owed_events(struct ast_bridge_channel *bridge_channel)
struct ast_bridge_channel * bridge_find_channel(struct ast_bridge *bridge, struct ast_channel *chan)
Definition: bridge.c:1498
int ast_bridge_channel_establish_roles(struct ast_bridge_channel *bridge_channel)
Clone the roles from a bridge_channel's attached ast_channel onto the bridge_channel's role list.
Definition: bridge_roles.c:443
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1169
struct ast_frame ast_null_frame
Definition: main/frame.c:79
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
void ast_bridge_publish_enter(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap)
Publish a bridge channel enter event.
ast_bridge_push_channel_fn push
Definition: bridge.h:269
enum ast_channel_state state
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_clear_flag(p, flag)
Definition: utils.h:77

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_cancel_owed_events(), 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_channel::entry, ast_bridge::feature_flags, ast_bridge_features::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_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_push(), and bridge_do_move().

◆ bridge_channel_internal_queue_attended_transfer()

int bridge_channel_internal_queue_attended_transfer ( struct ast_channel transferee,
struct ast_channel unbridged_chan 
)

Definition at line 3043 of file bridge_channel.c.

3045{
3046 RAII_VAR(struct ast_bridge_channel *, transferee_bridge_channel, NULL, ao2_cleanup);
3047 char unbridged_chan_name[AST_CHANNEL_NAME];
3048
3049 ast_channel_lock(transferee);
3050 transferee_bridge_channel = ast_channel_get_bridge_channel(transferee);
3051 ast_channel_unlock(transferee);
3052
3053 if (!transferee_bridge_channel) {
3054 return -1;
3055 }
3056
3057 ast_copy_string(unbridged_chan_name, ast_channel_name(unbridged_chan),
3058 sizeof(unbridged_chan_name));
3059
3060 return bridge_channel_queue_action_data(transferee_bridge_channel,
3061 BRIDGE_CHANNEL_ACTION_ATTENDED_TRANSFER, unbridged_chan_name,
3062 sizeof(unbridged_chan_name));
3063}
#define AST_CHANNEL_NAME
Definition: channel.h:173
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
Definition: channel.c:10587
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425

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

◆ bridge_channel_internal_queue_blind_transfer()

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 3017 of file bridge_channel.c.

3020{
3021 RAII_VAR(struct ast_bridge_channel *, transferee_bridge_channel, NULL, ao2_cleanup);
3022 struct blind_transfer_data blind_data;
3023
3024 ast_channel_lock(transferee);
3025 transferee_bridge_channel = ast_channel_get_bridge_channel(transferee);
3026 ast_channel_unlock(transferee);
3027
3028 if (!transferee_bridge_channel) {
3029 return -1;
3030 }
3031
3032 if (new_channel_cb) {
3033 new_channel_cb(transferee, user_data, AST_BRIDGE_TRANSFER_SINGLE_PARTY);
3034 }
3035
3036 ast_copy_string(blind_data.exten, exten, sizeof(blind_data.exten));
3037 ast_copy_string(blind_data.context, context, sizeof(blind_data.context));
3038
3039 return bridge_channel_queue_action_data(transferee_bridge_channel,
3040 BRIDGE_CHANNEL_ACTION_BLIND_TRANSFER, &blind_data, sizeof(blind_data));
3041}
@ AST_BRIDGE_TRANSFER_SINGLE_PARTY
Definition: bridge.h:1115
Data specifying where a blind transfer is going to.

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(), voicemailpwcheck::context, blind_transfer_data::context, blind_transfer_data::exten, NULL, and RAII_VAR.

Referenced by ast_bridge_transfer_blind().

◆ bridge_channel_internal_suspend_nolock()

void bridge_channel_internal_suspend_nolock ( struct ast_bridge_channel bridge_channel)

Definition at line 839 of file bridge_channel.c.

840{
841 bridge_channel->suspended = 1;
842 if (bridge_channel->in_bridge) {
843 --bridge_channel->bridge->num_active;
844 }
845
846 /* Get technology bridge threads off of the channel. */
847 if (bridge_channel->bridge->technology->suspend) {
848 bridge_channel->bridge->technology->suspend(bridge_channel->bridge, bridge_channel);
849 }
850}
void(* suspend)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Suspend a channel on a bridging technology instance for a bridge.

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

◆ bridge_channel_internal_unsuspend_nolock()

void bridge_channel_internal_unsuspend_nolock ( struct ast_bridge_channel bridge_channel)

Definition at line 865 of file bridge_channel.c.

866{
867 bridge_channel->suspended = 0;
868 if (bridge_channel->in_bridge) {
869 ++bridge_channel->bridge->num_active;
870 }
871
872 /* Wake technology bridge threads to take care of channel again. */
873 if (bridge_channel->bridge->technology->unsuspend) {
874 bridge_channel->bridge->technology->unsuspend(bridge_channel->bridge, bridge_channel);
875 }
876
877 /* Wake suspended channel. */
878 ast_bridge_channel_lock(bridge_channel);
879 ast_cond_signal(&bridge_channel->cond);
880 ast_bridge_channel_unlock(bridge_channel);
881}
#define ast_cond_signal(cond)
Definition: lock.h:210
void(* unsuspend)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Unsuspend a channel on a bridging technology instance for a bridge.

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

◆ bridge_channel_next_interval()

static int bridge_channel_next_interval ( struct ast_bridge_channel bridge_channel)
static

Definition at line 2652 of file bridge_channel.c.

2653{
2654 struct ast_heap *interval_hooks = bridge_channel->features->interval_hooks;
2655 struct ast_bridge_hook_timer *hook;
2656 int ms;
2657
2658 ast_heap_wrlock(interval_hooks);
2659 hook = ast_heap_peek(interval_hooks, 1);
2660 if (hook) {
2661 ms = ast_tvdiff_ms(hook->timer.trip_time, ast_tvnow());
2662 if (ms < 0) {
2663 /* Expire immediately. An interval hook is ready to run. */
2664 ms = 0;
2665 }
2666 } else {
2667 /* No hook so wait forever. */
2668 ms = -1;
2669 }
2670 ast_heap_unlock(interval_hooks);
2671
2672 return ms;
2673}

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

◆ bridge_channel_next_timeout()

static int bridge_channel_next_timeout ( struct ast_bridge_channel bridge_channel)
static

Definition at line 2714 of file bridge_channel.c.

2715{
2716 int ms_interval;
2717 int ms;
2718
2719 ms_interval = bridge_channel_next_interval(bridge_channel);
2720 ms = bridge_channel_feature_timeout(bridge_channel);
2721 if (ms < 0 || (0 <= ms_interval && ms_interval < ms)) {
2722 /* Interval hook timeout is next. */
2723 ms = ms_interval;
2724 }
2725
2726 return ms;
2727}
static int bridge_channel_feature_timeout(struct ast_bridge_channel *bridge_channel)
static int bridge_channel_next_interval(struct ast_bridge_channel *bridge_channel)

References bridge_channel_feature_timeout(), and bridge_channel_next_interval().

Referenced by bridge_channel_wait().

◆ bridge_channel_park()

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

Definition at line 1458 of file bridge_channel.c.

1459{
1461 ast_log(AST_LOG_WARNING, "Unable to park %s: No parking provider loaded!\n",
1462 ast_channel_name(bridge_channel->chan));
1463 return;
1464 }
1465
1466 if (ast_parking_park_bridge_channel(bridge_channel, payload->parkee_uuid,
1467 &payload->parkee_uuid[payload->parker_uuid_offset],
1468 payload->app_data_offset ? &payload->parkee_uuid[payload->app_data_offset] : NULL)) {
1469 ast_log(AST_LOG_WARNING, "Error occurred while parking %s\n",
1470 ast_channel_name(bridge_channel->chan));
1471 }
1472}
#define AST_LOG_WARNING
int ast_parking_park_bridge_channel(struct ast_bridge_channel *parkee, const char *parkee_uuid, const char *parker_uuid, const char *app_data)
Perform a direct park on a channel in a bridge.
Definition: parking.c:126
int ast_parking_provider_registered(void)
Check whether a parking provider is registered.
Definition: parking.c:241
char parkee_uuid[0]

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

◆ bridge_channel_playfile()

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

Definition at line 1317 of file bridge_channel.c.

1318{
1319 ast_bridge_channel_playfile(bridge_channel, payload->custom_play, payload->playfile,
1320 payload->moh_offset ? &payload->playfile[payload->moh_offset] : NULL);
1321}
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.
ast_bridge_custom_play_fn custom_play

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

Referenced by bridge_channel_handle_action().

◆ bridge_channel_poke()

static void bridge_channel_poke ( struct ast_bridge_channel bridge_channel)
static

Definition at line 260 of file bridge_channel.c.

261{
262 if (!pthread_equal(pthread_self(), bridge_channel->thread)) {
263 /* Wake up the bridge channel thread. */
264 ast_queue_frame(bridge_channel->chan, &ast_null_frame);
265 }
266}

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

Referenced by ast_bridge_channel_leave_bridge_nolock().

◆ bridge_channel_queue_action_data()

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

◆ bridge_channel_queue_action_data_sync()

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 937 of file bridge_channel.c.

939{
941 int sync_payload_len = sizeof(*sync_payload) + datalen;
942 struct bridge_sync sync_struct;
943 struct ast_frame frame = {
945 .subclass.integer = action,
946 };
947
948 /* Make sure we don't end up trying to wait on ourself to deliver the frame */
949 ast_assert(!pthread_equal(pthread_self(), bridge_channel->thread));
950
951 sync_payload = ast_alloca(sync_payload_len);
953 memcpy(sync_payload->data, data, datalen);
954
955 frame.datalen = sync_payload_len;
956 frame.data.ptr = sync_payload;
957
958 bridge_sync_init(&sync_struct, sync_payload->id);
959 if (ast_bridge_channel_queue_frame(bridge_channel, &frame)) {
960 bridge_sync_cleanup(&sync_struct);
961 return -1;
962 }
963
964 bridge_sync_wait(&sync_struct);
965 bridge_sync_cleanup(&sync_struct);
966 return 0;
967}
static void bridge_sync_init(struct bridge_sync *sync_struct, unsigned int id)
Initialize a synchronous bridge object.
static void bridge_sync_wait(struct bridge_sync *sync_struct)
Wait for a synchronous bridge action to complete.
static void bridge_sync_cleanup(struct bridge_sync *sync_struct)
Clean up a synchronization bridge object.
static int sync_ids
Counter used for assigning synchronous bridge action IDs.
Synchronous bridge action object.
unsigned int id

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, sync_ids, and ast_bridge_channel::thread.

Referenced by ast_bridge_channel_queue_playfile_sync().

◆ bridge_channel_queue_deferred_frames()

void bridge_channel_queue_deferred_frames ( struct ast_bridge_channel bridge_channel)

Definition at line 825 of file bridge_channel.c.

826{
827 struct ast_frame *frame;
828
829 ast_bridge_channel_lock(bridge_channel);
830 ast_channel_lock(bridge_channel->chan);
831 while ((frame = AST_LIST_REMOVE_HEAD(&bridge_channel->deferred_queue, frame_list))) {
832 ast_queue_frame_head(bridge_channel->chan, frame);
833 ast_frfree(frame);
834 }
835 ast_channel_unlock(bridge_channel->chan);
836 ast_bridge_channel_unlock(bridge_channel);
837}
int ast_queue_frame_head(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to the head of a channel's frame queue.
Definition: channel.c:1174

References ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_channel_lock, ast_channel_unlock, ast_frfree, AST_LIST_REMOVE_HEAD, ast_queue_frame_head(), ast_bridge_channel::chan, and ast_bridge_channel::deferred_queue.

Referenced by bridge_complete_join().

◆ bridge_channel_run_app()

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

Definition at line 1225 of file bridge_channel.c.

1226{
1227 ast_bridge_channel_run_app(bridge_channel, data->app_name,
1228 data->app_args_offset ? &data->app_name[data->app_args_offset] : NULL,
1229 data->moh_offset ? &data->app_name[data->moh_offset] : NULL);
1230}
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.

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

◆ bridge_channel_settle_owed_events()

void bridge_channel_settle_owed_events ( struct ast_bridge orig_bridge,
struct ast_bridge_channel bridge_channel 
)

Definition at line 787 of file bridge_channel.c.

788{
789 if (bridge_channel->owed.dtmf_digit) {
790 struct ast_frame frame = {
792 .subclass.integer = bridge_channel->owed.dtmf_digit,
793 .src = "Bridge channel owed DTMF",
794 };
795
796 frame.len = ast_tvdiff_ms(ast_tvnow(), bridge_channel->owed.dtmf_tv);
797 if (frame.len < option_dtmfminduration) {
799 }
800 ast_log(LOG_DTMF, "DTMF end '%c' simulated to bridge %s because %s left. Duration %ld ms.\n",
801 bridge_channel->owed.dtmf_digit, orig_bridge->uniqueid,
802 ast_channel_name(bridge_channel->chan), frame.len);
803 bridge_channel->owed.dtmf_digit = '\0';
804 orig_bridge->technology->write(orig_bridge, NULL, &frame);
805 }
806 if (bridge_channel->owed.t38_terminate) {
807 struct ast_control_t38_parameters t38_parameters = {
809 };
810 struct ast_frame frame = {
812 .subclass.integer = AST_CONTROL_T38_PARAMETERS,
813 .data.ptr = &t38_parameters,
814 .datalen = sizeof(t38_parameters),
815 .src = "Bridge channel owed T.38 terminate",
816 };
817
818 ast_debug(1, "T.38 terminate simulated to bridge %s because %s left.\n",
819 orig_bridge->uniqueid, ast_channel_name(bridge_channel->chan));
820 bridge_channel->owed.t38_terminate = 0;
821 orig_bridge->technology->write(orig_bridge, NULL, &frame);
822 }
823}
unsigned int option_dtmfminduration
Definition: options.c:84
#define LOG_DTMF
struct timeval dtmf_tv
int(* write)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
Write a frame into the bridging technology instance for a bridge.
const char * src

References ast_channel_name(), AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, ast_log, AST_T38_TERMINATED, 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_control_t38_parameters::request_response, ast_frame::src, ast_bridge_channel::t38_terminate, ast_bridge::technology, ast_bridge::uniqueid, and ast_bridge_technology::write.

Referenced by bridge_channel_internal_join(), and bridge_do_move().

◆ bridge_channel_suspend()

static void bridge_channel_suspend ( struct ast_bridge_channel bridge_channel)
static

◆ bridge_channel_talking()

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

Definition at line 1840 of file bridge_channel.c.

1841{
1842 struct ast_bridge_features *features = bridge_channel->features;
1843 struct ast_bridge_hook *hook;
1844 struct ao2_iterator iter;
1845
1846 /* Run any talk detection hooks. */
1847 iter = ao2_iterator_init(features->other_hooks, 0);
1848 for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
1849 int remove_me;
1851
1852 if (hook->type != AST_BRIDGE_HOOK_TYPE_TALK) {
1853 continue;
1854 }
1856 remove_me = talk_cb(bridge_channel, hook->hook_pvt, talking);
1857 if (remove_me) {
1858 ast_debug(1, "Talk detection hook %p is being removed from %p(%s)\n",
1859 hook, bridge_channel, ast_channel_name(bridge_channel->chan));
1860 ao2_unlink(features->other_hooks, hook);
1861 }
1862 }
1863 ao2_iterator_destroy(&iter);
1864}
@ AST_BRIDGE_HOOK_TYPE_TALK
int(* ast_bridge_talking_indicate_callback)(struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking)
Talking indicator callback.

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

◆ bridge_channel_unsuspend()

static void bridge_channel_unsuspend ( struct ast_bridge_channel bridge_channel)
static

◆ bridge_channel_update_accountcodes_joining()

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

Definition at line 528 of file bridge_channel.c.

529{
530 struct ast_bridge *bridge = joining->bridge;
531 struct ast_bridge_channel *other;
532 unsigned int swap_in_bridge = 0;
533 unsigned int will_be_two_party;
534
535 /*
536 * Only update the peeraccount to match if the joining channel
537 * will make it a two party bridge.
538 */
539 if (bridge->num_channels <= 2 && swap) {
541 if (other == swap) {
542 swap_in_bridge = 1;
543 break;
544 }
545 }
546 }
547 will_be_two_party = (1 == bridge->num_channels - swap_in_bridge);
548
550 if (other == swap) {
551 continue;
552 }
553 ast_assert(joining != other);
554 ast_channel_lock_both(joining->chan, other->chan);
555 channel_set_empty_accountcodes(joining->chan, other->chan);
556 if (will_be_two_party) {
557 channel_update_peeraccounts(joining->chan, other->chan);
558 }
559 ast_channel_unlock(joining->chan);
560 ast_channel_unlock(other->chan);
561 }
562}
static void channel_set_empty_accountcodes(struct ast_channel *c0, struct ast_channel *c1)
static void channel_update_peeraccounts(struct ast_channel *c0, struct ast_channel *c1)
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2979

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, ast_bridge_channel::entry, ast_bridge::num_channels, and ast_bridge_channel::swap.

Referenced by ast_bridge_channel_update_accountcodes().

◆ bridge_channel_update_accountcodes_leaving()

static void bridge_channel_update_accountcodes_leaving ( struct ast_bridge_channel leaving)
static

Definition at line 573 of file bridge_channel.c.

574{
575 struct ast_bridge *bridge = leaving->bridge;
577 struct ast_bridge_channel *second;
578
579 if (bridge->num_channels != 2 || bridge->dissolved) {
580 return;
581 }
582
584 second = AST_LIST_LAST(&bridge->channels);
585 ast_assert(first && first != second);
586 ast_channel_lock_both(first->chan, second->chan);
588 channel_update_peeraccounts(first->chan, second->chan);
589 ast_channel_unlock(second->chan);
591}
struct sla_ringing_trunk * first
Definition: app_sla.c:338
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:429

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

◆ bridge_channel_wait()

static void bridge_channel_wait ( struct ast_bridge_channel bridge_channel)
static

Definition at line 2738 of file bridge_channel.c.

2739{
2740 int ms;
2741 int outfd;
2742 struct ast_channel *chan;
2743
2744 /* Wait for data to either come from the channel or us to be signaled */
2747 } else if (bridge_channel->suspended) {
2748/* XXX ASTERISK-21271 the external party use of suspended will go away as will these references because this is the bridge channel thread */
2749 ast_debug(1, "Bridge %s: %p(%s) is going into a signal wait\n",
2753 } else {
2755 outfd = -1;
2758 &bridge_channel->alert_pipe[0], 1, NULL, &outfd, &ms);
2765 }
2771 if (chan) {
2773 } else if (ms == 0) {
2774 /* An interdigit timeout or interval expired. */
2777 } else if (-1 < outfd) {
2778 /*
2779 * Must do this after checking timeouts or may have
2780 * an infinite loop due to deferring write queue
2781 * actions while trying to match DTMF feature hooks.
2782 */
2784 }
2785 }
2787 return;
2788 }
2790}
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
static void bridge_handle_trip(struct ast_bridge_channel *bridge_channel)
static int bridge_channel_next_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)
static void bridge_channel_handle_feature_timeout(struct ast_bridge_channel *bridge_channel)
@ BRIDGE_CHANNEL_THREAD_FRAME
@ BRIDGE_CHANNEL_THREAD_IDLE
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
Definition: channel.c:2956
void ast_channel_set_unbridged(struct ast_channel *chan, int value)
Sets the unbridged flag and queues a NULL frame on the channel to trigger a check by bridge_channel_w...
int ast_channel_unbridged(struct ast_channel *chan)
This function will check if the bridge needs to be re-evaluated due to external changes.
#define ast_cond_wait(cond, mutex)
Definition: lock.h:212

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, ast_channel::bridge_channel, 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().

◆ bridge_channel_write_action_data()

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 981 of file bridge_channel.c.

983{
984 struct ast_frame frame = {
986 .subclass.integer = action,
987 .datalen = datalen,
988 .data.ptr = (void *) data,
989 };
990
991 return bridge_channel_write_frame(bridge_channel, &frame);
992}

References AST_FRAME_BRIDGE_ACTION, bridge_channel_write_frame(), ast_frame::data, ast_frame::datalen, 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().

◆ bridge_channel_write_dtmf_stream()

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

Definition at line 1604 of file bridge_channel.c.

1605{
1606 return bridge_channel_write_action_data(bridge_channel,
1607 BRIDGE_CHANNEL_ACTION_DTMF_STREAM, dtmf, strlen(dtmf) + 1);
1608}

References BRIDGE_CHANNEL_ACTION_DTMF_STREAM, and bridge_channel_write_action_data().

Referenced by ast_bridge_channel_feature_digit().

◆ bridge_channel_write_frame()

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

Definition at line 647 of file bridge_channel.c.

648{
649 const struct ast_control_t38_parameters *t38_parameters;
650 int unmapped_stream_num;
651 int deferred;
652
654
655 ast_bridge_channel_lock_bridge(bridge_channel);
656
657 /*
658 * Map the frame to the bridge.
659 * We need to lock the bridge_channel to make sure that bridge_channel->chan
660 * isn't NULL and keep it locked while we do multistream processing.
661 */
662 ast_bridge_channel_lock(bridge_channel);
663 if (bridge_channel->chan && ast_channel_is_multistream(bridge_channel->chan)) {
664 unmapped_stream_num = frame->stream_num;
665 switch (frame->frametype) {
666 case AST_FRAME_VOICE:
667 case AST_FRAME_VIDEO:
668 case AST_FRAME_TEXT:
669 case AST_FRAME_IMAGE:
670 case AST_FRAME_RTCP:
671 /* These frames need to be mapped to an appropriate write stream */
672 if (frame->stream_num < 0) {
673 /* Map to default stream */
674 frame->stream_num = -1;
675 break;
676 }
677 if (frame->stream_num < (int)AST_VECTOR_SIZE(&bridge_channel->stream_map.to_bridge)) {
678 frame->stream_num = AST_VECTOR_GET(
679 &bridge_channel->stream_map.to_bridge, frame->stream_num);
680 if (0 <= frame->stream_num) {
681 break;
682 }
683 }
684 ast_bridge_channel_unlock(bridge_channel);
685 ast_bridge_unlock(bridge_channel->bridge);
686 /*
687 * Ignore frame because we don't know how to map the frame
688 * or the bridge is not expecting any media from that
689 * stream.
690 */
691 return 0;
694 /*
695 * XXX It makes sense that DTMF could be on any audio stream.
696 * For now we will only put it on the default audio stream.
697 */
698 default:
699 frame->stream_num = -1;
700 break;
701 }
702 } else {
703 unmapped_stream_num = -1;
704 frame->stream_num = -1;
705 }
706 ast_bridge_channel_unlock(bridge_channel);
707
708 deferred = bridge_channel->bridge->technology->write(bridge_channel->bridge, bridge_channel, frame);
709 if (deferred) {
710 struct ast_frame *dup;
711
712 dup = ast_frdup(frame);
713 if (dup) {
714 /*
715 * We have to unmap the deferred frame so it comes back
716 * in like a new frame.
717 */
718 dup->stream_num = unmapped_stream_num;
719 ast_bridge_channel_lock(bridge_channel);
720 AST_LIST_INSERT_HEAD(&bridge_channel->deferred_queue, dup, frame_list);
721 ast_bridge_channel_unlock(bridge_channel);
722 }
723 }
724
725 /* Remember any owed events to the bridge. */
726 switch (frame->frametype) {
728 bridge_channel->owed.dtmf_tv = ast_tvnow();
729 bridge_channel->owed.dtmf_digit = frame->subclass.integer;
730 break;
732 bridge_channel->owed.dtmf_digit = '\0';
733 break;
735 /*
736 * We explicitly will not remember HOLD/UNHOLD frames because
737 * things like attended transfers will handle them.
738 */
739 switch (frame->subclass.integer) {
741 t38_parameters = frame->data.ptr;
742 switch (t38_parameters->request_response) {
745 bridge_channel->owed.t38_terminate = 1;
746 break;
749 case AST_T38_REFUSED:
750 bridge_channel->owed.t38_terminate = 0;
751 break;
752 default:
753 break;
754 }
755 break;
756 default:
757 break;
758 }
759 break;
760 default:
761 break;
762 }
763 ast_bridge_unlock(bridge_channel->bridge);
764
765 /*
766 * Claim successful write to bridge. If deferred frame
767 * support is added, claim successfully deferred.
768 */
769 return 0;
770}
int ast_channel_is_multistream(struct ast_channel *chan)
Determine if a channel is multi-stream capable.
@ AST_T38_REFUSED
@ AST_T38_REQUEST_TERMINATE
@ AST_T38_NEGOTIATED
@ AST_T38_REQUEST_NEGOTIATE
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711

References ast_assert, ast_bridge_channel_lock, ast_bridge_channel_lock_bridge(), ast_bridge_channel_unlock, ast_bridge_unlock, ast_channel_is_multistream(), AST_CONTROL_T38_PARAMETERS, AST_FRAME_BRIDGE_ACTION_SYNC, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_IMAGE, AST_FRAME_RTCP, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup, AST_LIST_INSERT_HEAD, AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_tvnow(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_bridge_channel::bridge, ast_bridge_channel::chan, ast_frame::data, ast_bridge_channel::deferred_queue, ast_bridge_channel::dtmf_digit, ast_bridge_channel::dtmf_tv, ast_frame::frametype, ast_frame_subclass::integer, ast_bridge_channel::owed, ast_frame::ptr, ast_control_t38_parameters::request_response, ast_bridge_channel::stream_map, ast_frame::stream_num, ast_frame::subclass, ast_bridge_channel::t38_terminate, ast_bridge::technology, ast_bridge_channel::to_bridge, and ast_bridge_technology::write.

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

◆ bridge_frame_free()

static void bridge_frame_free ( struct ast_frame frame)
static

Definition at line 994 of file bridge_channel.c.

995{
997 struct sync_payload *sync_payload = frame->data.ptr;
998 struct bridge_sync *sync;
999
1002 if (sync->id == sync_payload->id) {
1003 break;
1004 }
1005 }
1006 if (sync) {
1007 bridge_sync_signal(sync);
1008 }
1010 }
1011
1012 ast_frfree(frame);
1013}
static void bridge_sync_signal(struct bridge_sync *sync_struct)
Signal that waiting for a synchronous bridge action is no longer necessary.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
unsigned int id
struct bridge_sync::@316 list
List holding active synchronous action objects.

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

◆ bridge_handle_dtmf()

static struct ast_frame * bridge_handle_dtmf ( struct ast_bridge_channel bridge_channel,
struct ast_frame frame 
)
static

Definition at line 2480 of file bridge_channel.c.

2481{
2482 struct ast_bridge_features *features = bridge_channel->features;
2483 struct ast_bridge_hook_dtmf *hook = NULL;
2484 char dtmf[2];
2485
2486 /*
2487 * See if we are already matching a DTMF feature hook sequence or
2488 * if this DTMF matches the beginning of any DTMF feature hooks.
2489 */
2490 dtmf[0] = frame->subclass.integer;
2491 dtmf[1] = '\0';
2492 if (bridge_channel->dtmf_hook_state.collected[0]
2493 || (hook = ao2_find(features->dtmf_hooks, dtmf, OBJ_SEARCH_PARTIAL_KEY))) {
2494 enum ast_frame_type frametype = frame->frametype;
2495
2496 bridge_frame_free(frame);
2497 frame = NULL;
2498
2499 ao2_cleanup(hook);
2500
2501 switch (frametype) {
2503 /* Just eat the frame. */
2504 break;
2505 case AST_FRAME_DTMF_END:
2506 ast_bridge_channel_feature_digit(bridge_channel, dtmf[0]);
2507 break;
2508 default:
2509 /* Unexpected frame type. */
2510 ast_assert(0);
2511 break;
2512 }
2513#ifdef TEST_FRAMEWORK
2514 } else if (frame->frametype == AST_FRAME_DTMF_END) {
2515 /* Only transmit this event on DTMF end or else every DTMF
2516 * press will result in the event being broadcast twice
2517 */
2518 ast_test_suite_event_notify("FEATURE_DETECTION", "Result: fail");
2519#endif
2520 }
2521
2522 return frame;
2523}
ast_frame_type
Frame types.

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

◆ bridge_handle_trip()

static void bridge_handle_trip ( struct ast_bridge_channel bridge_channel)
static

Definition at line 2540 of file bridge_channel.c.

2541{
2542 struct ast_frame *frame;
2543 int blocked;
2544
2545 if (!ast_strlen_zero(ast_channel_call_forward(bridge_channel->chan))) {
2546 /* TODO If early bridging is ever used by anything other than ARI,
2547 * it's important that we actually attempt to handle the call forward
2548 * attempt, as well as expand features on a bridge channel to allow/disallow
2549 * call forwarding. For now, all we do is raise an event, showing that
2550 * a call forward is being attempted.
2551 */
2552 ast_channel_publish_dial_forward(NULL, bridge_channel->chan, NULL, NULL, "CANCEL",
2553 ast_channel_call_forward(bridge_channel->chan));
2554 }
2555
2556 if (bridge_channel->features->mute) {
2557 frame = ast_read_stream_noaudio(bridge_channel->chan);
2558 } else {
2559 frame = ast_read_stream(bridge_channel->chan);
2560 }
2561
2562 if (!frame) {
2563 ast_bridge_channel_kick(bridge_channel, 0);
2564 return;
2565 }
2566
2567 if (!ast_channel_is_multistream(bridge_channel->chan)) {
2568 /* This may not be initialized by non-multistream channel drivers */
2569 frame->stream_num = -1;
2570 }
2571
2572 switch (frame->frametype) {
2573 case AST_FRAME_CONTROL:
2574 switch (frame->subclass.integer) {
2576 case AST_CONTROL_BUSY:
2577 ast_channel_publish_dial(NULL, bridge_channel->chan, NULL, controls[frame->subclass.integer]);
2578 break;
2579 case AST_CONTROL_HANGUP:
2580 ast_bridge_channel_kick(bridge_channel, 0);
2581 bridge_frame_free(frame);
2582 return;
2586 case AST_CONTROL_ANSWER:
2587 ast_channel_publish_dial(NULL, bridge_channel->chan, NULL, controls[frame->subclass.integer]);
2588 break;
2590 ast_bridge_channel_lock_bridge(bridge_channel);
2591 blocked = bridge_channel->bridge->technology->stream_topology_request_change
2593 bridge_channel->bridge, bridge_channel);
2594 ast_bridge_unlock(bridge_channel->bridge);
2595 if (blocked) {
2596 /*
2597 * Topology change was intercepted by the bridge technology
2598 * so drop frame.
2599 */
2600 bridge_frame_free(frame);
2601 return;
2602 }
2603 break;
2605 /*
2606 * If a stream topology has changed then the bridge_channel's
2607 * media mapping needs to be updated.
2608 */
2609 ast_bridge_channel_lock_bridge(bridge_channel);
2610 if (bridge_channel->bridge->technology->stream_topology_changed) {
2611 bridge_channel->bridge->technology->stream_topology_changed(
2612 bridge_channel->bridge, bridge_channel);
2613 } else {
2614 ast_bridge_channel_stream_map(bridge_channel);
2615 }
2616 ast_bridge_unlock(bridge_channel->bridge);
2617 break;
2618 default:
2619 break;
2620 }
2621 break;
2623 case AST_FRAME_DTMF_END:
2624 frame = bridge_handle_dtmf(bridge_channel, frame);
2625 if (!frame) {
2626 return;
2627 }
2628 if (!bridge_channel->features->dtmf_passthrough) {
2629 bridge_frame_free(frame);
2630 return;
2631 }
2632 break;
2633 default:
2634 break;
2635 }
2636
2637 /* Simply write the frame out to the bridge technology. */
2638 bridge_channel_write_frame(bridge_channel, frame);
2639 bridge_frame_free(frame);
2640}
static struct ast_frame * bridge_handle_dtmf(struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
static const char * controls[]
void ast_bridge_channel_stream_map(struct ast_bridge_channel *bridge_channel)
Maps a channel's stream topology to and from the bridge.
struct ast_frame * ast_read_stream(struct ast_channel *chan)
Reads a frame, but does not filter to just the default streams.
Definition: channel.c:4219
struct ast_frame * ast_read_stream_noaudio(struct ast_channel *chan)
Reads a frame, but does not filter to just the default streams, returning AST_FRAME_NULL frame if aud...
Definition: channel.c:4229
const char * ast_channel_call_forward(const struct ast_channel *chan)
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_channel *peer, struct ast_channel *forwarded, const char *dialstring, const char *dialstatus, const char *forward)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_BUSY
@ AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_RINGING
@ AST_CONTROL_HANGUP
int(* stream_topology_request_change)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Callback for when a request has been made to change a stream topology on a channel.
void(* stream_topology_changed)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Callback for when a stream topology changes on the channel.

References ast_bridge_channel_kick(), ast_bridge_channel_lock_bridge(), ast_bridge_channel_stream_map(), ast_bridge_unlock, ast_channel_call_forward(), ast_channel_is_multistream(), ast_channel_publish_dial(), ast_channel_publish_dial_forward(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_STREAM_TOPOLOGY_CHANGED, AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_read_stream(), ast_read_stream_noaudio(), ast_strlen_zero(), ast_bridge_channel::bridge, bridge_channel_write_frame(), bridge_frame_free(), bridge_handle_dtmf(), ast_bridge_channel::chan, controls, ast_bridge_features::dtmf_passthrough, ast_bridge_channel::features, ast_frame::frametype, ast_frame_subclass::integer, ast_bridge_features::mute, NULL, ast_frame::stream_num, ast_bridge_technology::stream_topology_changed, ast_bridge_technology::stream_topology_request_change, ast_frame::subclass, and ast_bridge::technology.

Referenced by bridge_channel_wait().

◆ bridge_sync_cleanup()

static void bridge_sync_cleanup ( struct bridge_sync sync_struct)
static

Clean up a synchronization 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_structSynchronization object to clean up.

Definition at line 148 of file bridge_channel.c.

149{
150 struct bridge_sync *iter;
151
154 if (iter->id == sync_struct->id) {
156 break;
157 }
158 }
161
162 ast_sem_destroy(&sync_struct->sem);
163}
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
int ast_sem_destroy(struct ast_sem *sem)
Destroy a semaphore.
struct ast_sem sem

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

◆ bridge_sync_init()

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_structThe synchronization object to initialize.
idID to assign to the synchronization object.

Definition at line 125 of file bridge_channel.c.

126{
127 memset(sync_struct, 0, sizeof(*sync_struct));
128 sync_struct->id = id;
129 ast_sem_init(&sync_struct->sem, 0, 0);
130
132 AST_RWLIST_INSERT_TAIL(&sync_structs, sync_struct, list);
134}
enum queue_result id
Definition: app_queue.c:1808
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
int ast_sem_init(struct ast_sem *sem, int pshared, unsigned int value)
Initialize a semaphore.

References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_sem_init(), id, bridge_sync::id, and bridge_sync::sem.

Referenced by bridge_channel_queue_action_data_sync().

◆ bridge_sync_signal()

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_structSynchronization object corresponding to the bridge action.

Definition at line 207 of file bridge_channel.c.

208{
209 ast_sem_post(&sync_struct->sem);
210}
int ast_sem_post(struct ast_sem *sem)
Increments the semaphore, unblocking a waiter if necessary.

References ast_sem_post(), and bridge_sync::sem.

Referenced by bridge_frame_free().

◆ bridge_sync_wait()

static void bridge_sync_wait ( struct bridge_sync sync_struct)
static

Wait for a synchronous bridge action to complete.

Parameters
sync_structSynchronization object corresponding to the bridge action.

Definition at line 186 of file bridge_channel.c.

187{
188 struct timeval timeout_val = ast_tvadd(ast_tvnow(), ast_samp2tv(PLAYBACK_TIMEOUT, 1000));
189 struct timespec timeout_spec = {
190 .tv_sec = timeout_val.tv_sec,
191 .tv_nsec = timeout_val.tv_usec * 1000,
192 };
193
194 ast_sem_timedwait(&sync_struct->sem, &timeout_spec);
195}
#define PLAYBACK_TIMEOUT
Failsafe for synchronous bridge action waiting.
int ast_sem_timedwait(struct ast_sem *sem, const struct timespec *abs_timeout)
Decrements the semaphore, waiting until abs_timeout.

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

Referenced by bridge_channel_queue_action_data_sync().

◆ channel_fill_empty_accountcode()

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

Definition at line 450 of file bridge_channel.c.

451{
454 ast_debug(1, "Setting channel %s accountcode with channel %s peeraccount '%s'.\n",
455 ast_channel_name(dest),
457 ast_channel_accountcode_set(dest, ast_channel_peeraccount(src));
458 }
459}
const char * ast_channel_accountcode(const struct ast_channel *chan)
const char * ast_channel_peeraccount(const struct ast_channel *chan)

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

Referenced by channel_set_empty_accountcodes().

◆ channel_fill_empty_peeraccount()

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

Definition at line 429 of file bridge_channel.c.

430{
433 ast_debug(1, "Setting channel %s peeraccount with channel %s accountcode '%s'.\n",
434 ast_channel_name(dest),
436 ast_channel_peeraccount_set(dest, ast_channel_accountcode(src));
437 }
438}

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

Referenced by channel_set_empty_accountcodes().

◆ channel_set_cause()

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

Definition at line 279 of file bridge_channel.c.

280{
281 int current_cause;
282 ast_channel_lock(chan);
283 current_cause = ast_channel_hangupcause(chan);
284
285 /* if the hangupcause is already set, leave it */
286 if (current_cause > 0) {
287 ast_channel_unlock(chan);
288 return current_cause;
289 }
290
291 if (cause <= 0) {
292 cause = ast_channel_hangupcause(chan);
293 if (cause <= 0) {
295 }
296 }
297
298 ast_channel_hangupcause_set(chan, cause);
299 ast_channel_unlock(chan);
300 return cause;
301}
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)

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

◆ channel_set_empty_accountcodes()

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

Definition at line 471 of file bridge_channel.c.

472{
473 /* Set empty peeraccount from the other channel's accountcode. */
476
477 /* Set empty accountcode from the other channel's peeraccount. */
480}
static void channel_fill_empty_peeraccount(struct ast_channel *dest, struct ast_channel *src)
static void channel_fill_empty_accountcode(struct ast_channel *dest, struct ast_channel *src)

References channel_fill_empty_accountcode(), and channel_fill_empty_peeraccount().

Referenced by bridge_channel_update_accountcodes_joining(), and bridge_channel_update_accountcodes_leaving().

◆ channel_update_peeraccount()

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

Definition at line 492 of file bridge_channel.c.

493{
494 if (strcmp(ast_channel_accountcode(src), ast_channel_peeraccount(dest))) {
495 ast_debug(1, "Changing channel %s peeraccount '%s' to match channel %s accountcode '%s'.\n",
498 ast_channel_peeraccount_set(dest, ast_channel_accountcode(src));
499 }
500}

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

Referenced by channel_update_peeraccounts().

◆ channel_update_peeraccounts()

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

Definition at line 512 of file bridge_channel.c.

513{
516}
static void channel_update_peeraccount(struct ast_channel *dest, struct ast_channel *src)

References channel_update_peeraccount().

Referenced by bridge_channel_update_accountcodes_joining(), and bridge_channel_update_accountcodes_leaving().

◆ payload_helper_app()

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 1236 of file bridge_channel.c.

1238{
1239 struct bridge_run_app *app_data;
1240 size_t len_name = strlen(app_name) + 1;
1241 size_t len_args = ast_strlen_zero(app_args) ? 0 : strlen(app_args) + 1;
1242 size_t len_moh = !moh_class ? 0 : strlen(moh_class) + 1;
1243 size_t len_data = sizeof(*app_data) + len_name + len_args + len_moh;
1244
1245 /* Fill in application run frame data. */
1246 app_data = alloca(len_data);
1247 app_data->app_args_offset = len_args ? len_name : 0;
1248 app_data->moh_offset = len_moh ? len_name + len_args : 0;
1249 strcpy(app_data->app_name, app_name);/* Safe */
1250 if (len_args) {
1251 strcpy(&app_data->app_name[app_data->app_args_offset], app_args);/* Safe */
1252 }
1253 if (moh_class) {
1254 strcpy(&app_data->app_name[app_data->moh_offset], moh_class);/* Safe */
1255 }
1256
1257 return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_RUN_APP, app_data, len_data);
1258}

References app_name(), ast_strlen_zero(), and BRIDGE_CHANNEL_ACTION_RUN_APP.

Referenced by ast_bridge_channel_queue_app(), and ast_bridge_channel_write_app().

◆ payload_helper_cb()

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 1404 of file bridge_channel.c.

1408{
1409 struct bridge_custom_callback *cb_data;
1410 size_t len_data = sizeof(*cb_data) + (payload ? payload_size : 0);
1411
1412 /* Sanity check. */
1413 if (!callback) {
1414 ast_assert(0);
1415 return -1;
1416 }
1417
1418 /* Fill in custom callback frame data. */
1419 cb_data = alloca(len_data);
1420 cb_data->callback = callback;
1421 cb_data->payload_size = payload_size;
1422 cb_data->flags = flags;
1423 cb_data->payload_exists = payload && payload_size;
1424 if (cb_data->payload_exists) {
1425 memcpy(cb_data->payload, payload, payload_size);/* Safe */
1426 }
1427
1428 return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_CALLBACK, cb_data, len_data);
1429}

References ast_assert, BRIDGE_CHANNEL_ACTION_CALLBACK, bridge_custom_callback::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().

◆ payload_helper_park()

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 1478 of file bridge_channel.c.

1483{
1484 struct bridge_park *payload;
1485 size_t len_parkee_uuid = strlen(parkee_uuid) + 1;
1486 size_t len_parker_uuid = strlen(parker_uuid) + 1;
1487 size_t len_app_data = !app_data ? 0 : strlen(app_data) + 1;
1488 size_t len_payload = sizeof(*payload) + len_parker_uuid + len_parkee_uuid + len_app_data;
1489
1490 payload = alloca(len_payload);
1491 payload->app_data_offset = len_app_data ? len_parkee_uuid + len_parker_uuid : 0;
1492 payload->parker_uuid_offset = len_parkee_uuid;
1493 strcpy(payload->parkee_uuid, parkee_uuid);
1494 strcpy(&payload->parkee_uuid[payload->parker_uuid_offset], parker_uuid);
1495 if (app_data) {
1496 strcpy(&payload->parkee_uuid[payload->app_data_offset], app_data);
1497 }
1498
1499 return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_PARK, payload, len_payload);
1500}

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

◆ payload_helper_playfile()

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 1327 of file bridge_channel.c.

1329{
1330 struct bridge_playfile *payload;
1331 size_t len_name = strlen(playfile) + 1;
1332 size_t len_moh = !moh_class ? 0 : strlen(moh_class) + 1;
1333 size_t len_payload = sizeof(*payload) + len_name + len_moh;
1334
1335 /* Fill in play file frame data. */
1336 payload = ast_alloca(len_payload);
1337 payload->custom_play = custom_play;
1338 payload->moh_offset = len_moh ? len_name : 0;
1339 strcpy(payload->playfile, playfile);/* Safe */
1340 if (moh_class) {
1341 strcpy(&payload->playfile[payload->moh_offset], moh_class);/* Safe */
1342 }
1343
1344 return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_PLAY_FILE, payload, len_payload);
1345}

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

◆ run_app_helper()

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

Definition at line 1182 of file bridge_channel.c.

1183{
1184 int res = 0;
1185
1186 if (!strcasecmp("Gosub", app_name)) {
1187 ast_app_exec_sub(NULL, chan, app_args, 0);
1188 } else {
1189 res = ast_pbx_exec_application(chan, app_name, app_args);
1190 }
1191 return res;
1192}
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
Definition: main/app.c:297
int ast_pbx_exec_application(struct ast_channel *chan, const char *app_name, const char *app_args)
Execute an application.
Definition: pbx_app.c:501

References app_name(), ast_app_exec_sub(), ast_pbx_exec_application(), and NULL.

Referenced by ast_bridge_channel_run_app().

◆ sendtext_safe()

static void sendtext_safe ( struct ast_channel chan,
const struct ast_frame f 
)
static

Definition at line 2340 of file bridge_channel.c.

2341{
2342 if (f->datalen) {
2343 char *text = f->data.ptr;
2344
2345 if (text[f->datalen - 1]) {
2346 /* Not zero terminated, we need to allocate */
2348 if (!text) {
2349 return;
2350 }
2351 }
2352
2353 ast_sendtext(chan, text);
2354
2355 if (text != f->data.ptr) {
2356 /* Only free if we allocated */
2357 ast_free(text);
2358 }
2359 } else {
2360 /* Special case if the frame length is zero (although I
2361 * am not sure this is possible?) */
2362 ast_sendtext(chan, "");
2363 }
2364}
char * text
Definition: app_queue.c:1809
#define ast_free(a)
Definition: astmm.h:180
#define ast_strndup(str, len)
A wrapper for strndup()
Definition: astmm.h:256
int ast_sendtext(struct ast_channel *chan, const char *text)
Sends text to a channel.
Definition: channel.c:4768

References ast_free, ast_sendtext(), ast_strndup, ast_frame::data, ast_frame::datalen, ast_frame::ptr, and text.

Referenced by bridge_channel_handle_write().

◆ testsuite_notify_feature_success()

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

Definition at line 1620 of file bridge_channel.c.

1621{
1622#ifdef TEST_FRAMEWORK
1623 char *feature = "unknown";
1624 struct ast_featuremap_config *featuremap;
1625 struct ast_features_xfer_config *xfer;
1626
1627 ast_channel_lock(chan);
1628 featuremap = ast_get_chan_featuremap_config(chan);
1630 ast_channel_unlock(chan);
1631
1632 if (featuremap) {
1633 if (!strcmp(dtmf, featuremap->blindxfer)) {
1634 feature = "blindxfer";
1635 } else if (!strcmp(dtmf, featuremap->atxfer)) {
1636 feature = "atxfer";
1637 } else if (!strcmp(dtmf, featuremap->disconnect)) {
1638 feature = "disconnect";
1639 } else if (!strcmp(dtmf, featuremap->automixmon)) {
1640 feature = "automixmon";
1641 } else if (!strcmp(dtmf, featuremap->parkcall)) {
1642 feature = "parkcall";
1643 }
1644 }
1645 if (xfer) {
1646 if (!strcmp(dtmf, xfer->atxferthreeway)) {
1647 feature = "atxferthreeway";
1648 }
1649 }
1650
1651 ao2_cleanup(featuremap);
1652 ao2_cleanup(xfer);
1653
1654 ast_test_suite_event_notify("FEATURE_DETECTION",
1655 "Result: success\r\n"
1656 "Feature: %s", feature);
1657#endif /* TEST_FRAMEWORK */
1658}
struct ast_featuremap_config * ast_get_chan_featuremap_config(struct ast_channel *chan)
Get the featuremap configuration options for a channel.
struct ast_features_xfer_config * ast_get_chan_features_xfer_config(struct ast_channel *chan)
Get the transfer configuration options for a channel.
Configuration for the builtin features.
Feature configuration relating to transfers.

References ao2_cleanup, ast_channel_lock, ast_channel_unlock, 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::blindxfer, ast_featuremap_config::disconnect, and ast_featuremap_config::parkcall.

Referenced by ast_bridge_channel_feature_digit().

Variable Documentation

◆ controls

const char* controls[]
static

Definition at line 2525 of file bridge_channel.c.

Referenced by bridge_handle_trip().

◆ sync_ids

int sync_ids
static

Counter used for assigning synchronous bridge action IDs.

Definition at line 79 of file bridge_channel.c.

Referenced by bridge_channel_queue_action_data_sync().

◆ sync_structs

struct sync_structs sync_structs = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static