Asterisk - The Open Source Telephony Project GIT-master-0bf3178
Data Structures | Macros | Enumerations | Functions | Variables
bridge_basic.c File Reference

Basic bridge class. It is a subclass of struct ast_bridge. More...

#include "asterisk.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_internal.h"
#include "asterisk/bridge_basic.h"
#include "asterisk/bridge_after.h"
#include "asterisk/astobj2.h"
#include "asterisk/features_config.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/dial.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/features.h"
#include "asterisk/format_cache.h"
#include "asterisk/test.h"
Include dependency graph for bridge_basic.c:

Go to the source code of this file.

Data Structures

struct  attended_transfer_properties
 Collection of data related to an attended transfer attempt. More...
 
struct  attended_transfer_state_properties
 Properties of an attended transfer state. More...
 
struct  bridge_basic_personality
 structure that organizes different personalities for basic bridges. More...
 
struct  dynamic_dtmf_hook_data
 
struct  dynamic_dtmf_hook_run
 
struct  personality_details
 Details for specific basic bridge personalities. More...
 
struct  stimulus_list
 

Macros

#define NORMAL_FLAGS
 
#define TRANSFER_FLAGS   AST_BRIDGE_FLAG_SMART
 

Enumerations

enum  attended_transfer_state {
  TRANSFER_CALLING_TARGET , TRANSFER_HESITANT , TRANSFER_REBRIDGE , TRANSFER_RESUME ,
  TRANSFER_THREEWAY , TRANSFER_CONSULTING , TRANSFER_DOUBLECHECKING , TRANSFER_COMPLETE ,
  TRANSFER_BLOND , TRANSFER_BLOND_NONFINAL , TRANSFER_RECALLING , TRANSFER_WAIT_TO_RETRANSFER ,
  TRANSFER_RETRANSFER , TRANSFER_WAIT_TO_RECALL , TRANSFER_FAIL
}
 
enum  attended_transfer_state_flags {
  TRANSFER_STATE_FLAG_TIMER_RESET = (1 << 0) , TRANSFER_STATE_FLAG_TIMER_LOOP_DELAY = (1 << 1) , TRANSFER_STATE_FLAG_ATXFER_NO_ANSWER = (1 << 2) , TRANSFER_STATE_FLAG_TIMED ,
  TRANSFER_STATE_FLAG_TERMINAL = (1 << 3)
}
 Flags that indicate properties of attended transfer states. More...
 
enum  attended_transfer_stimulus {
  STIMULUS_NONE , STIMULUS_TRANSFEREE_HANGUP , STIMULUS_TRANSFERER_HANGUP , STIMULUS_TRANSFER_TARGET_HANGUP ,
  STIMULUS_TRANSFER_TARGET_ANSWER , STIMULUS_RECALL_TARGET_HANGUP , STIMULUS_RECALL_TARGET_ANSWER , STIMULUS_TIMEOUT ,
  STIMULUS_DTMF_ATXFER_ABORT , STIMULUS_DTMF_ATXFER_COMPLETE , STIMULUS_DTMF_ATXFER_THREEWAY , STIMULUS_DTMF_ATXFER_SWAP
}
 Stimuli that can cause transfer state changes. More...
 
enum  attended_transfer_superstate { SUPERSTATE_TRANSFER , SUPERSTATE_RECALL }
 Attended transfer superstates. More...
 
enum  bridge_basic_personality_type { BRIDGE_BASIC_PERSONALITY_NORMAL , BRIDGE_BASIC_PERSONALITY_ATXFER , BRIDGE_BASIC_PERSONALITY_END }
 

Functions

static int add_normal_hooks (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 
static int add_transferer_role (struct ast_channel *chan, struct ast_bridge_features_attended_transfer *attended_transfer)
 
struct ast_bridgeast_bridge_basic_new (void)
 Create a new basic class bridge. More...
 
void ast_bridge_basic_set_flags (struct ast_bridge *bridge, unsigned int flags)
 Set feature flags on a basic bridge. More...
 
int ast_bridge_features_ds_append (struct ast_channel *chan, struct ast_flags *flags)
 Append basic bridge DTMF feature flags on the channel. More...
 
struct ast_flagsast_bridge_features_ds_get (struct ast_channel *chan)
 Get DTMF feature flags from the channel. More...
 
int ast_bridge_features_ds_get_string (struct ast_channel *chan, char *buffer, size_t buf_size)
 writes a channel's DTMF features to a buffer string More...
 
int ast_bridge_features_ds_set (struct ast_channel *chan, struct ast_flags *flags)
 Set basic bridge DTMF feature flags datastore on the channel. More...
 
int ast_bridge_features_ds_set_string (struct ast_channel *chan, const char *features)
 Sets the features a channel will use upon being bridged. More...
 
void ast_bridging_init_basic (void)
 
static int attach_framehook (struct attended_transfer_properties *props, struct ast_channel *channel)
 
static void * attended_transfer_monitor_thread (void *data)
 The main loop for the attended transfer monitor thread. More...
 
static struct attended_transfer_propertiesattended_transfer_properties_alloc (struct ast_channel *transferer, const char *context)
 Allocate and initialize attended transfer properties. More...
 
static void attended_transfer_properties_destructor (void *obj)
 
static void attended_transfer_properties_shutdown (struct attended_transfer_properties *props)
 Initiate shutdown of attended transfer properties. More...
 
static int atxfer_abort (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 DTMF hook when transferer presses abort sequence. More...
 
static int atxfer_complete (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 DTMF hook when transferer presses complete sequence. More...
 
static int atxfer_swap (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 DTMF hook when transferer presses swap sequence. More...
 
static int atxfer_threeway (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 DTMF hook when transferer presses threeway sequence. More...
 
static int atxfer_transferer_hangup (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 Hangup hook for transferer channel. More...
 
static int basic_hangup_hook (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 
static void blind_transfer_cb (struct ast_channel *new_channel, struct transfer_channel_data *user_data_wrapper, enum ast_transfer_type transfer_type)
 
static int blond_enter (struct attended_transfer_properties *props)
 
static int blond_nonfinal_enter (struct attended_transfer_properties *props)
 
static enum attended_transfer_state blond_nonfinal_exit (struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
 
static void bridge_basic_change_personality (struct ast_bridge *bridge, enum bridge_basic_personality_type type, void *user_data)
 Change basic bridge personality. More...
 
static void bridge_basic_destroy (struct ast_bridge *self)
 
static struct ast_bridgebridge_basic_personality_alloc (struct ast_bridge *bridge)
 
static void bridge_basic_pull (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
 
static int bridge_basic_push (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
 
static int bridge_basic_setup_features (struct ast_bridge_channel *bridge_channel)
 
static int bridge_features_ds_set_full (struct ast_channel *chan, struct ast_flags *flags, int replace)
 
static void bridge_hold (struct ast_bridge *bridge)
 Helper method to send a hold frame to all channels in a bridge. More...
 
static void bridge_merge (struct ast_bridge *dest, struct ast_bridge *src, struct ast_channel **kick_channels, unsigned int num_channels)
 Wrapper for bridge_do_merge. More...
 
static void bridge_move (struct ast_bridge *dest, struct ast_bridge *src, struct ast_channel *channel, struct ast_channel *swap)
 Wrapper for bridge_do_move. More...
 
static void bridge_personality_atxfer_pull (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
 
static int bridge_personality_atxfer_push (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
 
static int bridge_personality_normal_push (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
 
static void bridge_ringing (struct ast_bridge *bridge)
 Helper method to send a ringing indication to all channels in a bridge. More...
 
static void bridge_unhold (struct ast_bridge *bridge)
 Helper method to send an unhold frame to all channels in a bridge. More...
 
static int build_dtmf_features (struct ast_flags *flags, const char *features)
 
static int builtin_feature_get_exten (struct ast_channel *chan, const char *feature_name, char *buf, size_t len)
 
static int builtin_features_helper (struct ast_bridge_features *features, struct ast_channel *chan, struct ast_flags *flags, unsigned int feature_flag, const char *feature_name, enum ast_bridge_builtin_feature feature_bridge)
 
static int calling_target_enter (struct attended_transfer_properties *props)
 
static enum attended_transfer_state calling_target_exit (struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
 
static void clear_stimulus_queue (struct attended_transfer_properties *props)
 Free backlog of stimuli in the queue. More...
 
static void common_recall_channel_setup (struct ast_channel *recall, struct ast_channel *transferer)
 
static int complete_enter (struct attended_transfer_properties *props)
 
static int consulting_enter (struct attended_transfer_properties *props)
 
static enum attended_transfer_state consulting_exit (struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
 
static void copy_caller_data (struct ast_channel *dest, struct ast_channel *caller)
 
static struct ast_channeldial_transfer (struct ast_channel *caller, const char *destination)
 Helper function that creates an outgoing channel and returns it immediately. More...
 
static int double_checking_enter (struct attended_transfer_properties *props)
 
static enum attended_transfer_state double_checking_exit (struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
 
static int dtmf_features_flags_to_string (struct ast_flags *feature_flags, char *buffer, size_t buffer_size)
 
static int dynamic_dtmf_hook_add (struct ast_bridge_features *features, unsigned int flags, const char *dtmf, const char *feature_name, const char *app_name, const char *app_args, const char *moh_class)
 
static void dynamic_dtmf_hook_callback (struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
 
static int dynamic_dtmf_hook_trip (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 
static int fail_enter (struct attended_transfer_properties *props)
 
static int feature_attended_transfer (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 Internal built in feature for attended transfers. More...
 
static int feature_blind_transfer (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 Internal built in feature for blind transfers. More...
 
static const char * get_transfer_context (struct ast_channel *transferer, const char *context)
 
static const char * get_transfer_exten (struct ast_channel *transferer, const char *exten)
 
static void get_transfer_parties (struct ast_channel *transferer, struct ast_bridge *transferee_bridge, struct ast_bridge *target_bridge, struct ast_channel **transferee, struct ast_channel **transfer_target)
 determine transferee and transfer target for an attended transfer More...
 
static void get_transfer_parties_transferer_bridge (struct ast_bridge *transferer_bridge, struct ast_bridge *other_bridge, struct ast_channel *transferer, struct ast_channel **transferer_peer, struct ast_channel **other_party)
 Get the transferee and transfer target when the transferer is in a bridge with one of the desired parties. More...
 
static void get_transfer_party_non_transferer_bridge (struct ast_bridge *bridge, struct ast_channel **party)
 Get a desired transfer party for a bridge the transferer is not in. More...
 
static int grab_transfer (struct ast_channel *chan, char *exten, size_t exten_len, const char *context)
 Helper function that presents dialtone and grabs extension. More...
 
static int hesitant_enter (struct attended_transfer_properties *props)
 
static enum attended_transfer_state hesitant_exit (struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
 
static void hold (struct ast_channel *chan)
 Helper method to place a channel in a bridge on hold. More...
 
static void init_details (struct personality_details *details, enum bridge_basic_personality_type type)
 
static void on_personality_change_normal (struct ast_bridge *bridge)
 
static void personality_destructor (void *obj)
 
static void play_failsound (struct ast_channel *chan)
 Helper method to play a fail sound on a channel in a bridge. More...
 
static void play_sound (struct ast_channel *chan, const char *sound)
 Helper method to play a sound on a channel in a bridge. More...
 
static void publish_transfer_fail (struct attended_transfer_properties *props)
 Send a stasis publication for a failed attended transfer. More...
 
static void publish_transfer_success (struct attended_transfer_properties *props, struct ast_channel *transferee_channel, struct ast_channel *target_channel)
 Send a stasis publication for a successful attended transfer. More...
 
static void publish_transfer_threeway (struct attended_transfer_properties *props, struct ast_channel *transferee_channel, struct ast_channel *target_channel)
 Send a stasis publication for an attended transfer that ends in a threeway call. More...
 
static int rebridge_enter (struct attended_transfer_properties *props)
 
static void recall_callback (struct ast_dial *dial)
 Dial callback when attempting to recall the original transferer channel. More...
 
static void recall_pull (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct attended_transfer_properties *props)
 
static int recalling_enter (struct attended_transfer_properties *props)
 
static enum attended_transfer_state recalling_exit (struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
 
static void remove_attended_transfer_stimulus (struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
 
static void remove_hooks_on_personality_change (struct ast_bridge *bridge)
 Remove appropriate hooks when basic bridge personality changes. More...
 
static int resume_enter (struct attended_transfer_properties *props)
 
static int retransfer_enter (struct attended_transfer_properties *props)
 
static enum attended_transfer_state retransfer_exit (struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
 
static void ringing (struct ast_channel *chan)
 Helper method to send a ringing indication to a channel in a bridge. More...
 
static int set_feature_flag_from_char (struct ast_flags *feature_flags, char feature)
 
static int setup_bridge_features_builtin (struct ast_bridge_features *features, struct ast_channel *chan)
 
static int setup_bridge_features_dynamic (struct ast_bridge_features *features, struct ast_channel *chan)
 
static int setup_dynamic_feature (void *obj, void *arg, void *data, int flags)
 
static void stimulate_attended_transfer (struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
 
static void stream_failsound (struct ast_channel *chan)
 Helper method to stream a fail sound on a channel. More...
 
static int threeway_enter (struct attended_transfer_properties *props)
 
static void transfer_pull (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct attended_transfer_properties *props)
 
static struct ast_frametransfer_target_framehook_cb (struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
 Frame hook for transfer target channel. More...
 
static int transfer_target_framehook_consume (void *data, enum ast_frame_type type)
 Callback function which informs upstream if we are consuming a frame of a specific type. More...
 
static void transfer_target_framehook_destroy_cb (void *data)
 
static void unhold (struct ast_channel *chan)
 Helper method to take a channel in a bridge off hold. More...
 
static enum attended_transfer_stimulus wait_for_stimulus (struct attended_transfer_properties *props)
 
static int wait_to_recall_enter (struct attended_transfer_properties *props)
 
static enum attended_transfer_state wait_to_recall_exit (struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
 
static int wait_to_retransfer_enter (struct attended_transfer_properties *props)
 
static enum attended_transfer_state wait_to_retransfer_exit (struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
 

Variables

struct ast_bridge_methods ast_bridge_basic_v_table
 Bridge basic class virtual method table. More...
 
static const struct ast_datastore_info dtmf_features_info
 
struct ast_bridge_methods personality_atxfer_v_table
 
struct ast_bridge_methods personality_normal_v_table
 
static const struct attended_transfer_state_properties state_properties []
 
const char * stimulus_strs []
 String representations of the various stimuli. More...
 

Detailed Description

Basic bridge class. It is a subclass of struct ast_bridge.

Author
Richard Mudgett rmudg.nosp@m.ett@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

See Also:

Definition in file bridge_basic.c.

Macro Definition Documentation

◆ NORMAL_FLAGS

#define NORMAL_FLAGS
Value:

Definition at line 51 of file bridge_basic.c.

◆ TRANSFER_FLAGS

#define TRANSFER_FLAGS   AST_BRIDGE_FLAG_SMART

Definition at line 54 of file bridge_basic.c.

Enumeration Type Documentation

◆ attended_transfer_state

The states in the attended transfer state machine.

Enumerator
TRANSFER_CALLING_TARGET 

Calling Target state.

This state describes the initial state of a transfer. The transferer waits in the transfer target's bridge for the transfer target to answer.

Superstate: Transfer

Preconditions: 1) Transfer target is RINGING 2) Transferer is in transferee bridge 3) Transferee is on hold

Transitions to TRANSFER_CALLING_TARGET: 1) This is the initial state for an attended transfer. 2) TRANSFER_HESITANT: Transferer presses DTMF swap sequence

State operation: The transferer is moved from the transferee bridge into the transfer target bridge.

Transitions from TRANSFER_CALLING_TARGET: 1) TRANSFER_FAIL: Transferee hangs up. 2) TRANSFER_BLOND: Transferer hangs up or presses DTMF swap sequence and configured atxferdropcall setting is yes. 3) TRANSFER_BLOND_NONFINAL: Transferer hangs up or presses DTMF swap sequence and configured atxferdropcall setting is no. 4) TRANSFER_CONSULTING: Transfer target answers the call. 5) TRANSFER_REBRIDGE: Transfer target hangs up, call to transfer target times out, or transferer presses DTMF abort sequence. 6) TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence. 7) TRANSFER_HESITANT: Transferer presses DTMF swap sequence.

TRANSFER_HESITANT 

Hesitant state.

This state only arises if when waiting for the transfer target to answer, the transferer presses the DTMF swap sequence. This will cause the transferer to be rebridged with the transferee temporarily.

Superstate: Transfer

Preconditions: 1) Transfer target is in ringing state 2) Transferer is in transfer target bridge 3) Transferee is on hold

Transitions to TRANSFER_HESITANT: 1) TRANSFER_CALLING_TARGET: Transferer presses DTMF swap sequence.

State operation: The transferer is moved from the transfer target bridge into the transferee bridge, and the transferee is taken off hold.

Transitions from TRANSFER_HESITANT: 1) TRANSFER_FAIL: Transferee hangs up 2) TRANSFER_BLOND: Transferer hangs up or presses DTMF swap sequence and configured atxferdropcall setting is yes. 3) TRANSFER_BLOND_NONFINAL: Transferer hangs up or presses DTMF swap sequence and configured atxferdropcall setting is no. 4) TRANSFER_DOUBLECHECKING: Transfer target answers the call 5) TRANSFER_RESUME: Transfer target hangs up, call to transfer target times out, or transferer presses DTMF abort sequence. 6) TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence. 7) TRANSFER_CALLING_TARGET: Transferer presses DTMF swap sequence.

TRANSFER_REBRIDGE 

Rebridge state.

This is a terminal state that indicates that the transferer needs to move back to the transferee's bridge. This is a failed attended transfer result.

Superstate: Transfer

Preconditions: 1) Transferer is in transfer target bridge 2) Transferee is on hold

Transitions to TRANSFER_REBRIDGE: 1) TRANSFER_CALLING_TARGET: Transfer target hangs up, call to transfer target times out, or transferer presses DTMF abort sequence. 2) TRANSFER_STATE_CONSULTING: Transfer target hangs up, or transferer presses DTMF abort sequence.

State operation: The transferer channel is moved from the transfer target bridge to the transferee bridge. The transferee is taken off hold. A stasis transfer message is published indicating a failed attended transfer.

Transitions from TRANSFER_REBRIDGE: None

TRANSFER_RESUME 

Resume state.

This is a terminal state that indicates that the party bridged with the transferee is the final party to be bridged with that transferee. This state may come about due to a successful recall or due to a failed transfer.

Superstate: Transfer or Recall

Preconditions: In Transfer Superstate: 1) Transferer is in transferee bridge 2) Transferee is not on hold In Recall Superstate: 1) The recall target is in the transferee bridge 2) Transferee is not on hold

Transitions to TRANSFER_RESUME: TRANSFER_HESITANT: Transfer target hangs up, call to transfer target times out, or transferer presses DTMF abort sequence. TRANSFER_DOUBLECHECKING: Transfer target hangs up or transferer presses DTMF abort sequence. TRANSFER_BLOND_NONFINAL: Recall target answers TRANSFER_RECALLING: Recall target answers TRANSFER_RETRANSFER: Recall target answers

State operations: None

Transitions from TRANSFER_RESUME: None

TRANSFER_THREEWAY 

Threeway state.

This state results when the transferer wishes to have all parties involved in a transfer to be in the same bridge together.

Superstate: Transfer

Preconditions: 1) Transfer target state is either RINGING or UP 2) Transferer is in either bridge 3) Transferee is not on hold

Transitions to TRANSFER_THREEWAY: 1) TRANSFER_CALLING_TARGET: Transferer presses DTMF threeway sequence. 2) TRANSFER_HESITANT: Transferer presses DTMF threeway sequence. 3) TRANSFER_CONSULTING: Transferer presses DTMF threeway sequence. 4) TRANSFER_DOUBLECHECKING: Transferer presses DTMF threeway sequence.

State operation: The transfer target bridge is merged into the transferee bridge.

Transitions from TRANSFER_THREEWAY: None.

TRANSFER_CONSULTING 

Consulting state.

This state describes the case where the transferer and transfer target are able to converse in the transfer target's bridge prior to completing the transfer.

Superstate: Transfer

Preconditions: 1) Transfer target is UP 2) Transferer is in target bridge 3) Transferee is on hold

Transitions to TRANSFER_CONSULTING: 1) TRANSFER_CALLING_TARGET: Transfer target answers. 2) TRANSFER_DOUBLECHECKING: Transferer presses DTMF swap sequence.

State operations: None.

Transitions from TRANSFER_CONSULTING: TRANSFER_COMPLETE: Transferer hangs up or transferer presses DTMF complete sequence. TRANSFER_REBRIDGE: Transfer target hangs up or transferer presses DTMF abort sequence. TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence. TRANSFER_DOUBLECHECKING: Transferer presses DTMF swap sequence.

TRANSFER_DOUBLECHECKING 

Double-checking state.

This state describes the case where the transferer and transferee are able to converse in the transferee's bridge prior to completing the transfer. The difference between this and TRANSFER_HESITANT is that the transfer target is UP in this case.

Superstate: Transfer

Preconditions: 1) Transfer target is UP and on hold 2) Transferer is in transferee bridge 3) Transferee is off hold

Transitions to TRANSFER_DOUBLECHECKING: 1) TRANSFER_HESITANT: Transfer target answers. 2) TRANSFER_CONSULTING: Transferer presses DTMF swap sequence.

State operations: None.

Transitions from TRANSFER_DOUBLECHECKING: 1) TRANSFER_FAIL: Transferee hangs up. 2) TRANSFER_COMPLETE: Transferer hangs up or presses DTMF complete sequence. 3) TRANSFER_RESUME: Transfer target hangs up or transferer presses DTMF abort sequence. 4) TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence. 5) TRANSFER_CONSULTING: Transferer presses the DTMF swap sequence.

TRANSFER_COMPLETE 

Complete state.

This is a terminal state where a transferer has successfully completed an attended transfer. This state's goal is to get the transfer target and transferee into the same bridge and the transferer off the call.

Superstate: Transfer

Preconditions: 1) Transfer target is UP and off hold. 2) Transferer is in either bridge. 3) Transferee is off hold.

Transitions to TRANSFER_COMPLETE: 1) TRANSFER_CONSULTING: transferer hangs up or presses the DTMF complete sequence. 2) TRANSFER_DOUBLECHECKING: transferer hangs up or presses the DTMF complete sequence.

State operation: The transfer target bridge is merged into the transferee bridge. The transferer channel is kicked out of the bridges as part of the merge.

State operations: 1) Merge the transfer target bridge into the transferee bridge, excluding the transferer channel from the merge. 2) Publish a stasis transfer message.

Exit operations: This is a terminal state, so there are no exit operations.

TRANSFER_BLOND 

Blond state.

This is a terminal state where a transferer has completed an attended transfer prior to the transfer target answering. This state is only entered if atxferdropcall is set to 'yes'. This is considered to be a successful attended transfer.

Superstate: Transfer

Preconditions: 1) Transfer target is RINGING. 2) Transferer is in either bridge. 3) Transferee is off hold.

Transitions to TRANSFER_BLOND: 1) TRANSFER_CALLING_TARGET: Transferer hangs up or presses the DTMF complete sequence. atxferdropcall is set to 'yes'. 2) TRANSFER_HESITANT: Transferer hangs up or presses the DTMF complete sequence. atxferdropcall is set to 'yes'.

State operations: The transfer target bridge is merged into the transferee bridge. The transferer channel is kicked out of the bridges as part of the merge. A stasis transfer publication is sent indicating a successful transfer.

Transitions from TRANSFER_BLOND: None

TRANSFER_BLOND_NONFINAL 

Blond non-final state.

This state is very similar to the TRANSFER_BLOND state, except that this state is entered when atxferdropcall is set to 'no'. This is the initial state of the Recall superstate, so state operations mainly involve moving to the Recall superstate. This means that the transfer target, that is currently ringing is now known as the recall target.

Superstate: Recall

Preconditions: 1) Recall target is RINGING. 2) Transferee is off hold.

Transitions to TRANSFER_BLOND_NONFINAL: 1) TRANSFER_CALLING_TARGET: Transferer hangs up or presses the DTMF complete sequence. atxferdropcall is set to 'no'. 2) TRANSFER_HESITANT: Transferer hangs up or presses the DTMF complete sequence. atxferdropcall is set to 'no'.

State operation: The superstate of the attended transfer is changed from Transfer to Recall. The transfer target bridge is merged into the transferee bridge. The transferer channel is kicked out of the bridges as part of the merge.

Transitions from TRANSFER_BLOND_NONFINAL: 1) TRANSFER_FAIL: Transferee hangs up 2) TRANSFER_RESUME: Recall target answers 3) TRANSFER_RECALLING: Recall target hangs up or time expires.

TRANSFER_RECALLING 

Recalling state.

This state is entered if the recall target from the TRANSFER_BLOND_NONFINAL or TRANSFER_RETRANSFER states hangs up or does not answer. The goal of this state is to call back the original transferer in an attempt to recover the original call.

Superstate: Recall

Preconditions: 1) Recall target is down. 2) Transferee is off hold.

Transitions to TRANSFER_RECALLING: 1) TRANSFER_BLOND_NONFINAL: Recall target hangs up or time expires. 2) TRANSFER_RETRANSFER: Recall target hangs up or time expires. atxferloopdelay is non-zero. 3) TRANSFER_WAIT_TO_RECALL: Time expires.

State operation: The original transferer becomes the recall target and is called using the Dialing API. Ringing is indicated to the transferee.

Transitions from TRANSFER_RECALLING: 1) TRANSFER_FAIL: a) Transferee hangs up. b) Recall target hangs up or time expires, and number of recall attempts exceeds atxfercallbackretries 2) TRANSFER_WAIT_TO_RETRANSFER: Recall target hangs up or time expires. atxferloopdelay is non-zero. 3) TRANSFER_RETRANSFER: Recall target hangs up or time expires. atxferloopdelay is zero. 4) TRANSFER_RESUME: Recall target answers.

TRANSFER_WAIT_TO_RETRANSFER 

Wait to Retransfer state.

This state is used simply to give a bit of breathing room between attempting to call back the original transferer and attempting to call back the original transfer target. The transferee hears music on hold during this state as an auditory clue that no one is currently being dialed.

Superstate: Recall

Preconditions: 1) Recall target is down. 2) Transferee is off hold.

Transitions to TRANSFER_WAIT_TO_RETRANSFER: 1) TRANSFER_RECALLING: Recall target hangs up or time expires. atxferloopdelay is non-zero.

State operation: The transferee is placed on hold.

Transitions from TRANSFER_WAIT_TO_RETRANSFER: 1) TRANSFER_FAIL: Transferee hangs up. 2) TRANSFER_RETRANSFER: Time expires.

TRANSFER_RETRANSFER 

Retransfer state.

This state is used in order to attempt to call back the original transfer target channel from the transfer. The transferee hears ringing during this state as an auditory cue that a party is being dialed.

Superstate: Recall

Preconditions: 1) Recall target is down. 2) Transferee is off hold.

Transitions to TRANSFER_RETRANSFER: 1) TRANSFER_RECALLING: Recall target hangs up or time expires. atxferloopdelay is zero. 2) TRANSFER_WAIT_TO_RETRANSFER: Time expires.

State operation: The original transfer target is requested and is set as the recall target. The recall target is called and placed into the transferee bridge.

Transitions from TRANSFER_RETRANSFER: 1) TRANSFER_FAIL: Transferee hangs up. 2) TRANSFER_WAIT_TO_RECALL: Recall target hangs up or time expires. atxferloopdelay is non-zero. 3) TRANSFER_RECALLING: Recall target hangs up or time expires. atxferloopdelay is zero.

TRANSFER_WAIT_TO_RECALL 

Wait to recall state.

This state is used simply to give a bit of breathing room between attempting to call back the original transfer target and attempting to call back the original transferer. The transferee hears music on hold during this state as an auditory clue that no one is currently being dialed.

Superstate: Recall

Preconditions: 1) Recall target is down. 2) Transferee is off hold.

Transitions to TRANSFER_WAIT_TO_RECALL: 1) TRANSFER_RETRANSFER: Recall target hangs up or time expires. atxferloopdelay is non-zero.

State operation: Transferee is placed on hold.

Transitions from TRANSFER_WAIT_TO_RECALL: 1) TRANSFER_FAIL: Transferee hangs up 2) TRANSFER_RECALLING: Time expires

TRANSFER_FAIL 

Fail state.

This state indicates that something occurred during the transfer that makes a graceful completion impossible. The most common stimulus for this state is when the transferee hangs up.

Superstate: Transfer and Recall

Preconditions: None

Transitions to TRANSFER_FAIL: 1) TRANSFER_CALLING_TARGET: Transferee hangs up. 2) TRANSFER_HESITANT: Transferee hangs up. 3) TRANSFER_DOUBLECHECKING: Transferee hangs up. 4) TRANSFER_BLOND_NONFINAL: Transferee hangs up. 5) TRANSFER_RECALLING: a) Transferee hangs up. b) Recall target hangs up or time expires, and number of recall attempts exceeds atxfercallbackretries. 6) TRANSFER_WAIT_TO_RETRANSFER: Transferee hangs up. 7) TRANSFER_RETRANSFER: Transferee hangs up. 8) TRANSFER_WAIT_TO_RECALL: Transferee hangs up.

State operation: A transfer stasis publication is made indicating a failed transfer. The transferee bridge is destroyed.

Transitions from TRANSFER_FAIL: None.

Definition at line 773 of file bridge_basic.c.

773 {
774 /*!
775 * \brief Calling Target state
776 *
777 * This state describes the initial state of a transfer. The transferer
778 * waits in the transfer target's bridge for the transfer target to answer.
779 *
780 * Superstate: Transfer
781 *
782 * Preconditions:
783 * 1) Transfer target is RINGING
784 * 2) Transferer is in transferee bridge
785 * 3) Transferee is on hold
786 *
787 * Transitions to TRANSFER_CALLING_TARGET:
788 * 1) This is the initial state for an attended transfer.
789 * 2) TRANSFER_HESITANT: Transferer presses DTMF swap sequence
790 *
791 * State operation:
792 * The transferer is moved from the transferee bridge into the transfer
793 * target bridge.
794 *
795 * Transitions from TRANSFER_CALLING_TARGET:
796 * 1) TRANSFER_FAIL: Transferee hangs up.
797 * 2) TRANSFER_BLOND: Transferer hangs up or presses DTMF swap sequence
798 * and configured atxferdropcall setting is yes.
799 * 3) TRANSFER_BLOND_NONFINAL: Transferer hangs up or presses DTMF swap
800 * sequence and configured atxferdropcall setting is no.
801 * 4) TRANSFER_CONSULTING: Transfer target answers the call.
802 * 5) TRANSFER_REBRIDGE: Transfer target hangs up, call to transfer target
803 * times out, or transferer presses DTMF abort sequence.
804 * 6) TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence.
805 * 7) TRANSFER_HESITANT: Transferer presses DTMF swap sequence.
806 */
808 /*!
809 * \brief Hesitant state
810 *
811 * This state only arises if when waiting for the transfer target to
812 * answer, the transferer presses the DTMF swap sequence. This will
813 * cause the transferer to be rebridged with the transferee temporarily.
814 *
815 * Superstate: Transfer
816 *
817 * Preconditions:
818 * 1) Transfer target is in ringing state
819 * 2) Transferer is in transfer target bridge
820 * 3) Transferee is on hold
821 *
822 * Transitions to TRANSFER_HESITANT:
823 * 1) TRANSFER_CALLING_TARGET: Transferer presses DTMF swap sequence.
824 *
825 * State operation:
826 * The transferer is moved from the transfer target bridge into the
827 * transferee bridge, and the transferee is taken off hold.
828 *
829 * Transitions from TRANSFER_HESITANT:
830 * 1) TRANSFER_FAIL: Transferee hangs up
831 * 2) TRANSFER_BLOND: Transferer hangs up or presses DTMF swap sequence
832 * and configured atxferdropcall setting is yes.
833 * 3) TRANSFER_BLOND_NONFINAL: Transferer hangs up or presses DTMF swap
834 * sequence and configured atxferdropcall setting is no.
835 * 4) TRANSFER_DOUBLECHECKING: Transfer target answers the call
836 * 5) TRANSFER_RESUME: Transfer target hangs up, call to transfer target
837 * times out, or transferer presses DTMF abort sequence.
838 * 6) TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence.
839 * 7) TRANSFER_CALLING_TARGET: Transferer presses DTMF swap sequence.
840 */
842 /*!
843 * \brief Rebridge state
844 *
845 * This is a terminal state that indicates that the transferer needs
846 * to move back to the transferee's bridge. This is a failed attended
847 * transfer result.
848 *
849 * Superstate: Transfer
850 *
851 * Preconditions:
852 * 1) Transferer is in transfer target bridge
853 * 2) Transferee is on hold
854 *
855 * Transitions to TRANSFER_REBRIDGE:
856 * 1) TRANSFER_CALLING_TARGET: Transfer target hangs up, call to transfer target
857 * times out, or transferer presses DTMF abort sequence.
858 * 2) TRANSFER_STATE_CONSULTING: Transfer target hangs up, or transferer presses
859 * DTMF abort sequence.
860 *
861 * State operation:
862 * The transferer channel is moved from the transfer target bridge to the
863 * transferee bridge. The transferee is taken off hold. A stasis transfer
864 * message is published indicating a failed attended transfer.
865 *
866 * Transitions from TRANSFER_REBRIDGE:
867 * None
868 */
870 /*!
871 * \brief Resume state
872 *
873 * This is a terminal state that indicates that the party bridged with the
874 * transferee is the final party to be bridged with that transferee. This state
875 * may come about due to a successful recall or due to a failed transfer.
876 *
877 * Superstate: Transfer or Recall
878 *
879 * Preconditions:
880 * In Transfer Superstate:
881 * 1) Transferer is in transferee bridge
882 * 2) Transferee is not on hold
883 * In Recall Superstate:
884 * 1) The recall target is in the transferee bridge
885 * 2) Transferee is not on hold
886 *
887 * Transitions to TRANSFER_RESUME:
888 * TRANSFER_HESITANT: Transfer target hangs up, call to transfer target times out,
889 * or transferer presses DTMF abort sequence.
890 * TRANSFER_DOUBLECHECKING: Transfer target hangs up or transferer presses DTMF
891 * abort sequence.
892 * TRANSFER_BLOND_NONFINAL: Recall target answers
893 * TRANSFER_RECALLING: Recall target answers
894 * TRANSFER_RETRANSFER: Recall target answers
895 *
896 * State operations:
897 * None
898 *
899 * Transitions from TRANSFER_RESUME:
900 * None
901 */
903 /*!
904 * \brief Threeway state
905 *
906 * This state results when the transferer wishes to have all parties involved
907 * in a transfer to be in the same bridge together.
908 *
909 * Superstate: Transfer
910 *
911 * Preconditions:
912 * 1) Transfer target state is either RINGING or UP
913 * 2) Transferer is in either bridge
914 * 3) Transferee is not on hold
915 *
916 * Transitions to TRANSFER_THREEWAY:
917 * 1) TRANSFER_CALLING_TARGET: Transferer presses DTMF threeway sequence.
918 * 2) TRANSFER_HESITANT: Transferer presses DTMF threeway sequence.
919 * 3) TRANSFER_CONSULTING: Transferer presses DTMF threeway sequence.
920 * 4) TRANSFER_DOUBLECHECKING: Transferer presses DTMF threeway sequence.
921 *
922 * State operation:
923 * The transfer target bridge is merged into the transferee bridge.
924 *
925 * Transitions from TRANSFER_THREEWAY:
926 * None.
927 */
929 /*!
930 * \brief Consulting state
931 *
932 * This state describes the case where the transferer and transfer target
933 * are able to converse in the transfer target's bridge prior to completing
934 * the transfer.
935 *
936 * Superstate: Transfer
937 *
938 * Preconditions:
939 * 1) Transfer target is UP
940 * 2) Transferer is in target bridge
941 * 3) Transferee is on hold
942 *
943 * Transitions to TRANSFER_CONSULTING:
944 * 1) TRANSFER_CALLING_TARGET: Transfer target answers.
945 * 2) TRANSFER_DOUBLECHECKING: Transferer presses DTMF swap sequence.
946 *
947 * State operations:
948 * None.
949 *
950 * Transitions from TRANSFER_CONSULTING:
951 * TRANSFER_COMPLETE: Transferer hangs up or transferer presses DTMF complete sequence.
952 * TRANSFER_REBRIDGE: Transfer target hangs up or transferer presses DTMF abort sequence.
953 * TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence.
954 * TRANSFER_DOUBLECHECKING: Transferer presses DTMF swap sequence.
955 */
957 /*!
958 * \brief Double-checking state
959 *
960 * This state describes the case where the transferer and transferee are
961 * able to converse in the transferee's bridge prior to completing the transfer. The
962 * difference between this and TRANSFER_HESITANT is that the transfer target is
963 * UP in this case.
964 *
965 * Superstate: Transfer
966 *
967 * Preconditions:
968 * 1) Transfer target is UP and on hold
969 * 2) Transferer is in transferee bridge
970 * 3) Transferee is off hold
971 *
972 * Transitions to TRANSFER_DOUBLECHECKING:
973 * 1) TRANSFER_HESITANT: Transfer target answers.
974 * 2) TRANSFER_CONSULTING: Transferer presses DTMF swap sequence.
975 *
976 * State operations:
977 * None.
978 *
979 * Transitions from TRANSFER_DOUBLECHECKING:
980 * 1) TRANSFER_FAIL: Transferee hangs up.
981 * 2) TRANSFER_COMPLETE: Transferer hangs up or presses DTMF complete sequence.
982 * 3) TRANSFER_RESUME: Transfer target hangs up or transferer presses DTMF abort sequence.
983 * 4) TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence.
984 * 5) TRANSFER_CONSULTING: Transferer presses the DTMF swap sequence.
985 */
987 /*!
988 * \brief Complete state
989 *
990 * This is a terminal state where a transferer has successfully completed an attended
991 * transfer. This state's goal is to get the transfer target and transferee into
992 * the same bridge and the transferer off the call.
993 *
994 * Superstate: Transfer
995 *
996 * Preconditions:
997 * 1) Transfer target is UP and off hold.
998 * 2) Transferer is in either bridge.
999 * 3) Transferee is off hold.
1000 *
1001 * Transitions to TRANSFER_COMPLETE:
1002 * 1) TRANSFER_CONSULTING: transferer hangs up or presses the DTMF complete sequence.
1003 * 2) TRANSFER_DOUBLECHECKING: transferer hangs up or presses the DTMF complete sequence.
1004 *
1005 * State operation:
1006 * The transfer target bridge is merged into the transferee bridge. The transferer
1007 * channel is kicked out of the bridges as part of the merge.
1008 *
1009 * State operations:
1010 * 1) Merge the transfer target bridge into the transferee bridge,
1011 * excluding the transferer channel from the merge.
1012 * 2) Publish a stasis transfer message.
1013 *
1014 * Exit operations:
1015 * This is a terminal state, so there are no exit operations.
1016 */
1018 /*!
1019 * \brief Blond state
1020 *
1021 * This is a terminal state where a transferer has completed an attended transfer prior
1022 * to the transfer target answering. This state is only entered if atxferdropcall
1023 * is set to 'yes'. This is considered to be a successful attended transfer.
1024 *
1025 * Superstate: Transfer
1026 *
1027 * Preconditions:
1028 * 1) Transfer target is RINGING.
1029 * 2) Transferer is in either bridge.
1030 * 3) Transferee is off hold.
1031 *
1032 * Transitions to TRANSFER_BLOND:
1033 * 1) TRANSFER_CALLING_TARGET: Transferer hangs up or presses the DTMF complete sequence.
1034 * atxferdropcall is set to 'yes'.
1035 * 2) TRANSFER_HESITANT: Transferer hangs up or presses the DTMF complete sequence.
1036 * atxferdropcall is set to 'yes'.
1037 *
1038 * State operations:
1039 * The transfer target bridge is merged into the transferee bridge. The transferer
1040 * channel is kicked out of the bridges as part of the merge. A stasis transfer
1041 * publication is sent indicating a successful transfer.
1042 *
1043 * Transitions from TRANSFER_BLOND:
1044 * None
1045 */
1047 /*!
1048 * \brief Blond non-final state
1049 *
1050 * This state is very similar to the TRANSFER_BLOND state, except that
1051 * this state is entered when atxferdropcall is set to 'no'. This is the
1052 * initial state of the Recall superstate, so state operations mainly involve
1053 * moving to the Recall superstate. This means that the transfer target, that
1054 * is currently ringing is now known as the recall target.
1055 *
1056 * Superstate: Recall
1057 *
1058 * Preconditions:
1059 * 1) Recall target is RINGING.
1060 * 2) Transferee is off hold.
1061 *
1062 * Transitions to TRANSFER_BLOND_NONFINAL:
1063 * 1) TRANSFER_CALLING_TARGET: Transferer hangs up or presses the DTMF complete sequence.
1064 * atxferdropcall is set to 'no'.
1065 * 2) TRANSFER_HESITANT: Transferer hangs up or presses the DTMF complete sequence.
1066 * atxferdropcall is set to 'no'.
1067 *
1068 * State operation:
1069 * The superstate of the attended transfer is changed from Transfer to Recall.
1070 * The transfer target bridge is merged into the transferee bridge. The transferer
1071 * channel is kicked out of the bridges as part of the merge.
1072 *
1073 * Transitions from TRANSFER_BLOND_NONFINAL:
1074 * 1) TRANSFER_FAIL: Transferee hangs up
1075 * 2) TRANSFER_RESUME: Recall target answers
1076 * 3) TRANSFER_RECALLING: Recall target hangs up or time expires.
1077 */
1079 /*!
1080 * \brief Recalling state
1081 *
1082 * This state is entered if the recall target from the TRANSFER_BLOND_NONFINAL
1083 * or TRANSFER_RETRANSFER states hangs up or does not answer. The goal of this
1084 * state is to call back the original transferer in an attempt to recover the
1085 * original call.
1086 *
1087 * Superstate: Recall
1088 *
1089 * Preconditions:
1090 * 1) Recall target is down.
1091 * 2) Transferee is off hold.
1092 *
1093 * Transitions to TRANSFER_RECALLING:
1094 * 1) TRANSFER_BLOND_NONFINAL: Recall target hangs up or time expires.
1095 * 2) TRANSFER_RETRANSFER: Recall target hangs up or time expires.
1096 * atxferloopdelay is non-zero.
1097 * 3) TRANSFER_WAIT_TO_RECALL: Time expires.
1098 *
1099 * State operation:
1100 * The original transferer becomes the recall target and is called using the Dialing API.
1101 * Ringing is indicated to the transferee.
1102 *
1103 * Transitions from TRANSFER_RECALLING:
1104 * 1) TRANSFER_FAIL:
1105 * a) Transferee hangs up.
1106 * b) Recall target hangs up or time expires, and number of recall attempts exceeds atxfercallbackretries
1107 * 2) TRANSFER_WAIT_TO_RETRANSFER: Recall target hangs up or time expires.
1108 * atxferloopdelay is non-zero.
1109 * 3) TRANSFER_RETRANSFER: Recall target hangs up or time expires.
1110 * atxferloopdelay is zero.
1111 * 4) TRANSFER_RESUME: Recall target answers.
1112 */
1114 /*!
1115 * \brief Wait to Retransfer state
1116 *
1117 * This state is used simply to give a bit of breathing room between attempting
1118 * to call back the original transferer and attempting to call back the original
1119 * transfer target. The transferee hears music on hold during this state as an
1120 * auditory clue that no one is currently being dialed.
1121 *
1122 * Superstate: Recall
1123 *
1124 * Preconditions:
1125 * 1) Recall target is down.
1126 * 2) Transferee is off hold.
1127 *
1128 * Transitions to TRANSFER_WAIT_TO_RETRANSFER:
1129 * 1) TRANSFER_RECALLING: Recall target hangs up or time expires.
1130 * atxferloopdelay is non-zero.
1131 *
1132 * State operation:
1133 * The transferee is placed on hold.
1134 *
1135 * Transitions from TRANSFER_WAIT_TO_RETRANSFER:
1136 * 1) TRANSFER_FAIL: Transferee hangs up.
1137 * 2) TRANSFER_RETRANSFER: Time expires.
1138 */
1140 /*!
1141 * \brief Retransfer state
1142 *
1143 * This state is used in order to attempt to call back the original
1144 * transfer target channel from the transfer. The transferee hears
1145 * ringing during this state as an auditory cue that a party is being
1146 * dialed.
1147 *
1148 * Superstate: Recall
1149 *
1150 * Preconditions:
1151 * 1) Recall target is down.
1152 * 2) Transferee is off hold.
1153 *
1154 * Transitions to TRANSFER_RETRANSFER:
1155 * 1) TRANSFER_RECALLING: Recall target hangs up or time expires.
1156 * atxferloopdelay is zero.
1157 * 2) TRANSFER_WAIT_TO_RETRANSFER: Time expires.
1158 *
1159 * State operation:
1160 * The original transfer target is requested and is set as the recall target.
1161 * The recall target is called and placed into the transferee bridge.
1162 *
1163 * Transitions from TRANSFER_RETRANSFER:
1164 * 1) TRANSFER_FAIL: Transferee hangs up.
1165 * 2) TRANSFER_WAIT_TO_RECALL: Recall target hangs up or time expires.
1166 * atxferloopdelay is non-zero.
1167 * 3) TRANSFER_RECALLING: Recall target hangs up or time expires.
1168 * atxferloopdelay is zero.
1169 */
1171 /*!
1172 * \brief Wait to recall state
1173 *
1174 * This state is used simply to give a bit of breathing room between attempting
1175 * to call back the original transfer target and attempting to call back the
1176 * original transferer. The transferee hears music on hold during this state as an
1177 * auditory clue that no one is currently being dialed.
1178 *
1179 * Superstate: Recall
1180 *
1181 * Preconditions:
1182 * 1) Recall target is down.
1183 * 2) Transferee is off hold.
1184 *
1185 * Transitions to TRANSFER_WAIT_TO_RECALL:
1186 * 1) TRANSFER_RETRANSFER: Recall target hangs up or time expires.
1187 * atxferloopdelay is non-zero.
1188 *
1189 * State operation:
1190 * Transferee is placed on hold.
1191 *
1192 * Transitions from TRANSFER_WAIT_TO_RECALL:
1193 * 1) TRANSFER_FAIL: Transferee hangs up
1194 * 2) TRANSFER_RECALLING: Time expires
1195 */
1197 /*!
1198 * \brief Fail state
1199 *
1200 * This state indicates that something occurred during the transfer that
1201 * makes a graceful completion impossible. The most common stimulus for this
1202 * state is when the transferee hangs up.
1203 *
1204 * Superstate: Transfer and Recall
1205 *
1206 * Preconditions:
1207 * None
1208 *
1209 * Transitions to TRANSFER_FAIL:
1210 * 1) TRANSFER_CALLING_TARGET: Transferee hangs up.
1211 * 2) TRANSFER_HESITANT: Transferee hangs up.
1212 * 3) TRANSFER_DOUBLECHECKING: Transferee hangs up.
1213 * 4) TRANSFER_BLOND_NONFINAL: Transferee hangs up.
1214 * 5) TRANSFER_RECALLING:
1215 * a) Transferee hangs up.
1216 * b) Recall target hangs up or time expires, and number of
1217 * recall attempts exceeds atxfercallbackretries.
1218 * 6) TRANSFER_WAIT_TO_RETRANSFER: Transferee hangs up.
1219 * 7) TRANSFER_RETRANSFER: Transferee hangs up.
1220 * 8) TRANSFER_WAIT_TO_RECALL: Transferee hangs up.
1221 *
1222 * State operation:
1223 * A transfer stasis publication is made indicating a failed transfer.
1224 * The transferee bridge is destroyed.
1225 *
1226 * Transitions from TRANSFER_FAIL:
1227 * None.
1228 */
1230};
@ TRANSFER_WAIT_TO_RETRANSFER
Wait to Retransfer state.
@ TRANSFER_DOUBLECHECKING
Double-checking state.
Definition: bridge_basic.c:986
@ TRANSFER_COMPLETE
Complete state.
@ TRANSFER_REBRIDGE
Rebridge state.
Definition: bridge_basic.c:869
@ TRANSFER_RETRANSFER
Retransfer state.
@ TRANSFER_FAIL
Fail state.
@ TRANSFER_WAIT_TO_RECALL
Wait to recall state.
@ TRANSFER_HESITANT
Hesitant state.
Definition: bridge_basic.c:841
@ TRANSFER_BLOND
Blond state.
@ TRANSFER_RESUME
Resume state.
Definition: bridge_basic.c:902
@ TRANSFER_THREEWAY
Threeway state.
Definition: bridge_basic.c:928
@ TRANSFER_CALLING_TARGET
Calling Target state.
Definition: bridge_basic.c:807
@ TRANSFER_CONSULTING
Consulting state.
Definition: bridge_basic.c:956
@ TRANSFER_RECALLING
Recalling state.
@ TRANSFER_BLOND_NONFINAL
Blond non-final state.

◆ attended_transfer_state_flags

Flags that indicate properties of attended transfer states.

Enumerator
TRANSFER_STATE_FLAG_TIMER_RESET 

This state requires that the timer be reset when entering the state

TRANSFER_STATE_FLAG_TIMER_LOOP_DELAY 

This state's timer uses atxferloopdelay

TRANSFER_STATE_FLAG_ATXFER_NO_ANSWER 

This state's timer uses atxfernoanswertimeout

TRANSFER_STATE_FLAG_TIMED 

This state has a time limit associated with it

TRANSFER_STATE_FLAG_TERMINAL 

This state does not transition to any other states

Definition at line 1955 of file bridge_basic.c.

1955 {
1956 /*! This state requires that the timer be reset when entering the state */
1958 /*! This state's timer uses atxferloopdelay */
1960 /*! This state's timer uses atxfernoanswertimeout */
1962 /*! This state has a time limit associated with it */
1965 /*! This state does not transition to any other states */
1967};
@ TRANSFER_STATE_FLAG_TIMER_RESET
@ TRANSFER_STATE_FLAG_TIMED
@ TRANSFER_STATE_FLAG_TERMINAL
@ TRANSFER_STATE_FLAG_ATXFER_NO_ANSWER
@ TRANSFER_STATE_FLAG_TIMER_LOOP_DELAY

◆ attended_transfer_stimulus

Stimuli that can cause transfer state changes.

Enumerator
STIMULUS_NONE 

No stimulus. This literally can never happen.

STIMULUS_TRANSFEREE_HANGUP 

All of the transferee channels have been hung up.

STIMULUS_TRANSFERER_HANGUP 

The transferer has hung up.

STIMULUS_TRANSFER_TARGET_HANGUP 

The transfer target channel has hung up.

STIMULUS_TRANSFER_TARGET_ANSWER 

The transfer target channel has answered.

STIMULUS_RECALL_TARGET_HANGUP 

The recall target channel has hung up.

STIMULUS_RECALL_TARGET_ANSWER 

The recall target channel has answered.

STIMULUS_TIMEOUT 

The current state's timer has expired.

STIMULUS_DTMF_ATXFER_ABORT 

The transferer pressed the abort DTMF sequence.

STIMULUS_DTMF_ATXFER_COMPLETE 

The transferer pressed the complete DTMF sequence.

STIMULUS_DTMF_ATXFER_THREEWAY 

The transferer pressed the three-way DTMF sequence.

STIMULUS_DTMF_ATXFER_SWAP 

The transferer pressed the swap DTMF sequence.

Definition at line 1235 of file bridge_basic.c.

1235 {
1236 /*! No stimulus. This literally can never happen. */
1238 /*! All of the transferee channels have been hung up. */
1240 /*! The transferer has hung up. */
1242 /*! The transfer target channel has hung up. */
1244 /*! The transfer target channel has answered. */
1246 /*! The recall target channel has hung up. */
1248 /*! The recall target channel has answered. */
1250 /*! The current state's timer has expired. */
1252 /*! The transferer pressed the abort DTMF sequence. */
1254 /*! The transferer pressed the complete DTMF sequence. */
1256 /*! The transferer pressed the three-way DTMF sequence. */
1258 /*! The transferer pressed the swap DTMF sequence. */
1260};
@ STIMULUS_RECALL_TARGET_HANGUP
@ STIMULUS_RECALL_TARGET_ANSWER
@ STIMULUS_TRANSFER_TARGET_HANGUP
@ STIMULUS_TRANSFEREE_HANGUP
@ STIMULUS_DTMF_ATXFER_THREEWAY
@ STIMULUS_DTMF_ATXFER_ABORT
@ STIMULUS_TRANSFER_TARGET_ANSWER
@ STIMULUS_TRANSFERER_HANGUP
@ STIMULUS_DTMF_ATXFER_COMPLETE
@ STIMULUS_DTMF_ATXFER_SWAP
@ STIMULUS_TIMEOUT
@ STIMULUS_NONE

◆ attended_transfer_superstate

Attended transfer superstates.

An attended transfer's progress is facilitated by a state machine. The individual states of the state machine fall into the realm of one of two superstates.

Enumerator
SUPERSTATE_TRANSFER 

Transfer superstate.

The attended transfer state machine begins in this superstate. The goal of this state is for a transferer channel to facilitate a transfer from a transferee to a transfer target.

There are two bridges used in this superstate. The transferee bridge is the bridge that the transferer and transferee channels originally communicate in, and the target bridge is the bridge where the transfer target is being dialed.

The transferer channel is capable of moving between the bridges using the DTMF swap sequence.

SUPERSTATE_RECALL 

Recall superstate.

The attended transfer state machine moves to this superstate if atxferdropcall is set to "no" and the transferer channel hangs up during a transfer. The goal in this superstate is to call back either the transfer target or transferer and rebridge with the transferee channel(s).

In this superstate, there is only a single bridge used, the original transferee bridge. Rather than distinguishing between a transferer and transfer target, all outbound calls are toward a "recall_target" channel.

Definition at line 736 of file bridge_basic.c.

736 {
737 /*!
738 * \brief Transfer superstate
739 *
740 * The attended transfer state machine begins in this superstate. The
741 * goal of this state is for a transferer channel to facilitate a
742 * transfer from a transferee to a transfer target.
743 *
744 * There are two bridges used in this superstate. The transferee bridge is
745 * the bridge that the transferer and transferee channels originally
746 * communicate in, and the target bridge is the bridge where the transfer
747 * target is being dialed.
748 *
749 * The transferer channel is capable of moving between the bridges using
750 * the DTMF swap sequence.
751 */
753 /*!
754 * \brief Recall superstate
755 *
756 * The attended transfer state machine moves to this superstate if
757 * atxferdropcall is set to "no" and the transferer channel hangs up
758 * during a transfer. The goal in this superstate is to call back either
759 * the transfer target or transferer and rebridge with the transferee
760 * channel(s).
761 *
762 * In this superstate, there is only a single bridge used, the original
763 * transferee bridge. Rather than distinguishing between a transferer
764 * and transfer target, all outbound calls are toward a "recall_target"
765 * channel.
766 */
768};
@ SUPERSTATE_TRANSFER
Transfer superstate.
Definition: bridge_basic.c:752
@ SUPERSTATE_RECALL
Recall superstate.
Definition: bridge_basic.c:767

◆ bridge_basic_personality_type

Enumerator
BRIDGE_BASIC_PERSONALITY_NORMAL 

Index for "normal" basic bridge personality

BRIDGE_BASIC_PERSONALITY_ATXFER 

Index for attended transfer basic bridge personality

BRIDGE_BASIC_PERSONALITY_END 

Indicates end of enum. Must always remain the last element

Definition at line 58 of file bridge_basic.c.

58 {
59 /*! Index for "normal" basic bridge personality */
61 /*! Index for attended transfer basic bridge personality */
63 /*! Indicates end of enum. Must always remain the last element */
65};
@ BRIDGE_BASIC_PERSONALITY_NORMAL
Definition: bridge_basic.c:60
@ BRIDGE_BASIC_PERSONALITY_ATXFER
Definition: bridge_basic.c:62
@ BRIDGE_BASIC_PERSONALITY_END
Definition: bridge_basic.c:64

Function Documentation

◆ add_normal_hooks()

static int add_normal_hooks ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 640 of file bridge_basic.c.

641{
642 return ast_bridge_hangup_hook(bridge_channel->features, basic_hangup_hook,
644 || bridge_basic_setup_features(bridge_channel);
645}
static int basic_hangup_hook(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Definition: bridge_basic.c:290
static int bridge_basic_setup_features(struct ast_bridge_channel *bridge_channel)
Definition: bridge_basic.c:630
int ast_bridge_hangup_hook(struct ast_bridge_features *features, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a hangup hook to a bridge features structure.
Definition: bridge.c:3265
@ AST_BRIDGE_HOOK_REMOVE_ON_PULL
#define NULL
Definition: resample.c:96
struct ast_bridge_features * features

References ast_bridge_hangup_hook(), AST_BRIDGE_HOOK_REMOVE_ON_PULL, basic_hangup_hook(), bridge_basic_setup_features(), ast_bridge_channel::features, and NULL.

Referenced by bridge_personality_normal_push(), and on_personality_change_normal().

◆ add_transferer_role()

static int add_transferer_role ( struct ast_channel chan,
struct ast_bridge_features_attended_transfer attended_transfer 
)
static

Definition at line 3141 of file bridge_basic.c.

3142{
3143 const char *atxfer_abort;
3144 const char *atxfer_threeway;
3145 const char *atxfer_complete;
3146 const char *atxfer_swap;
3147 struct ast_features_xfer_config *xfer_cfg;
3148 SCOPED_CHANNELLOCK(lock, chan);
3149
3150 xfer_cfg = ast_get_chan_features_xfer_config(chan);
3151 if (!xfer_cfg) {
3152 return -1;
3153 }
3154 if (attended_transfer) {
3155 atxfer_abort = ast_strdupa(S_OR(attended_transfer->abort, xfer_cfg->atxferabort));
3156 atxfer_threeway = ast_strdupa(S_OR(attended_transfer->threeway, xfer_cfg->atxferthreeway));
3157 atxfer_complete = ast_strdupa(S_OR(attended_transfer->complete, xfer_cfg->atxfercomplete));
3158 atxfer_swap = ast_strdupa(S_OR(attended_transfer->swap, xfer_cfg->atxferswap));
3159 } else {
3163 atxfer_swap = ast_strdupa(xfer_cfg->atxferswap);
3164 }
3165 ao2_ref(xfer_cfg, -1);
3166
3172}
ast_mutex_t lock
Definition: app_sla.c:331
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
static int atxfer_complete(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses complete sequence.
static int atxfer_abort(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses abort sequence.
static int atxfer_swap(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses swap sequence.
static int atxfer_threeway(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses threeway sequence.
#define AST_TRANSFERER_ROLE_NAME
Definition: bridge_basic.h:36
int ast_channel_set_bridge_role_option(struct ast_channel *channel, const char *role_name, const char *option, const char *value)
Set a role option on a channel.
Definition: bridge_roles.c:375
int ast_channel_add_bridge_role(struct ast_channel *chan, const char *role_name)
Adds a bridge role to a channel.
Definition: bridge_roles.c:313
struct ast_features_xfer_config * ast_get_chan_features_xfer_config(struct ast_channel *chan)
Get the transfer configuration options for a channel.
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:619
#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
char swap[MAXIMUM_DTMF_FEATURE_STRING]
char threeway[MAXIMUM_DTMF_FEATURE_STRING]
char complete[MAXIMUM_DTMF_FEATURE_STRING]
char abort[MAXIMUM_DTMF_FEATURE_STRING]
Feature configuration relating to transfers.

References ast_bridge_features_attended_transfer::abort, ao2_ref, ast_channel_add_bridge_role(), ast_channel_set_bridge_role_option(), ast_get_chan_features_xfer_config(), ast_strdupa, AST_TRANSFERER_ROLE_NAME, atxfer_abort(), atxfer_complete(), atxfer_swap(), atxfer_threeway(), ast_features_xfer_config::atxferabort, ast_features_xfer_config::atxfercomplete, ast_features_xfer_config::atxferswap, ast_features_xfer_config::atxferthreeway, ast_bridge_features_attended_transfer::complete, lock, S_OR, SCOPED_CHANNELLOCK, ast_bridge_features_attended_transfer::swap, and ast_bridge_features_attended_transfer::threeway.

Referenced by feature_attended_transfer().

◆ ast_bridge_basic_new()

struct ast_bridge * ast_bridge_basic_new ( void  )

Create a new basic class bridge.

Returns
a pointer to a new bridge on success
Return values
NULLon failure

Example usage:

struct ast_bridge *bridge;
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
Structure that contains information about a bridge.
Definition: bridge.h:349

This creates a basic two party bridge with any configured DTMF features enabled that will be destroyed once one of the channels hangs up.

Definition at line 3661 of file bridge_basic.c.

3662{
3663 struct ast_bridge *bridge;
3664
3665 bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table);
3666 bridge = bridge_base_init(bridge,
3669 bridge = bridge_basic_personality_alloc(bridge);
3670 bridge = bridge_register(bridge);
3671 return bridge;
3672}
@ AST_BRIDGE_CAPABILITY_MULTIMIX
Definition: bridge.h:94
@ AST_BRIDGE_CAPABILITY_NATIVE
Definition: bridge.h:90
@ AST_BRIDGE_CAPABILITY_1TO1MIX
Definition: bridge.h:92
struct ast_bridge_methods ast_bridge_basic_v_table
Bridge basic class virtual method table.
static struct ast_bridge * bridge_basic_personality_alloc(struct ast_bridge *bridge)
#define NORMAL_FLAGS
Definition: bridge_basic.c:51
struct ast_bridge * bridge_register(struct ast_bridge *bridge)
Register the new bridge with the system.
Definition: bridge.c:691
struct ast_bridge * bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
Initialize the base class of the bridge.
Definition: bridge.c:742
struct ast_bridge * bridge_alloc(size_t size, const struct ast_bridge_methods *v_table)
Definition: bridge.c:706

References ast_bridge_basic_v_table, AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_CAPABILITY_MULTIMIX, AST_BRIDGE_CAPABILITY_NATIVE, bridge_alloc(), bridge_base_init(), bridge_basic_personality_alloc(), bridge_register(), NORMAL_FLAGS, and NULL.

Referenced by action_bridge(), agent_request_exec(), ast_bridge_call_with_flags(), AST_TEST_DEFINE(), bridge_exec(), feature_attended_transfer(), and parked_call_app_exec().

◆ ast_bridge_basic_set_flags()

void ast_bridge_basic_set_flags ( struct ast_bridge bridge,
unsigned int  flags 
)

Set feature flags on a basic bridge.

Using this function instead of setting flags directly will ensure that after operations such as an attended transfer, the bridge will maintain the flags that were set on it.

Parameters
bridge
flagsThese are added to the flags already set.

Definition at line 3674 of file bridge_basic.c.

3675{
3677 struct bridge_basic_personality *personality = bridge->personality;
3678
3679 personality->details[personality->current].bridge_flags |= flags;
3680 ast_set_flag(&bridge->feature_flags, flags);
3681}
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:481
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:470
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:583
void * personality
Definition: bridge.h:353
struct ast_flags feature_flags
Definition: bridge.h:369
structure that organizes different personalities for basic bridges.
Definition: bridge_basic.c:327
enum bridge_basic_personality_type current
Definition: bridge_basic.c:329
struct personality_details details[BRIDGE_BASIC_PERSONALITY_END]
Definition: bridge_basic.c:331
unsigned int bridge_flags
Definition: bridge_basic.c:317
#define ast_set_flag(p, flag)
Definition: utils.h:70

References ast_bridge_lock, ast_bridge_unlock, ast_set_flag, personality_details::bridge_flags, bridge_basic_personality::current, bridge_basic_personality::details, ast_bridge::feature_flags, lock, ast_bridge::personality, and SCOPED_LOCK.

Referenced by ast_bridge_call_with_flags().

◆ ast_bridge_features_ds_append()

int ast_bridge_features_ds_append ( struct ast_channel chan,
struct ast_flags flags 
)

Append basic bridge DTMF feature flags on the channel.

Since
12.0.0
Parameters
chanChannel to append DTMF features datastore.
flagsBuiltin DTMF feature flags. (ast_bridge_config flags)
Note
The channel must be locked before calling this function.
This function differs from ast_bridge_features_ds_set only in that it won't remove features already set on the channel.
Return values
0on success.
-1on error.

Definition at line 263 of file bridge_basic.c.

264{
265 return bridge_features_ds_set_full(chan, flags, 0);
266}
static int bridge_features_ds_set_full(struct ast_channel *chan, struct ast_flags *flags, int replace)
Definition: bridge_basic.c:224

References bridge_features_ds_set_full(), and ast_flags::flags.

Referenced by pre_bridge_setup().

◆ ast_bridge_features_ds_get()

struct ast_flags * ast_bridge_features_ds_get ( struct ast_channel chan)

Get DTMF feature flags from the channel.

Since
12.0.0
Parameters
chanChannel to get DTMF features datastore.
Note
The channel should be locked before calling this function.
The channel must remain locked until the flags returned have been consumed.
Returns
flags on success.
Return values
NULLif the datastore does not exist.

Definition at line 268 of file bridge_basic.c.

269{
270 struct ast_datastore *datastore;
271
273 if (!datastore) {
274 return NULL;
275 }
276 return datastore->data;
277}
static const struct ast_datastore_info dtmf_features_info
Definition: bridge_basic.c:82
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2418
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66

References ast_channel_datastore_find(), ast_datastore::data, dtmf_features_info, and NULL.

Referenced by ast_bridge_features_ds_get_string(), attended_transfer_properties_alloc(), parked_call_retrieve_enable_features(), and setup_bridge_features_builtin().

◆ ast_bridge_features_ds_get_string()

int ast_bridge_features_ds_get_string ( struct ast_channel chan,
char *  buffer,
size_t  buf_size 
)

writes a channel's DTMF features to a buffer string

Since
12.0.0
Parameters
chanchannel whose feature flags should be checked
bufferpointer string buffer where the output should be stored
buf_sizesize of the provided buffer (ideally enough for all features, 6+)
Return values
0on successful write
-1on failure

Definition at line 208 of file bridge_basic.c.

209{
210 struct ast_flags *channel_flags;
211 struct ast_flags held_copy;
212
213 ast_channel_lock(chan);
214 if (!(channel_flags = ast_bridge_features_ds_get(chan))) {
215 ast_channel_unlock(chan);
216 return -1;
217 }
218 held_copy = *channel_flags;
219 ast_channel_unlock(chan);
220
221 return dtmf_features_flags_to_string(&held_copy, buffer, buf_size);
222}
static int dtmf_features_flags_to_string(struct ast_flags *feature_flags, char *buffer, size_t buffer_size)
Definition: bridge_basic.c:133
struct ast_flags * ast_bridge_features_ds_get(struct ast_channel *chan)
Get DTMF feature flags from the channel.
Definition: bridge_basic.c:268
#define ast_channel_lock(chan)
Definition: channel.h:2968
#define ast_channel_unlock(chan)
Definition: channel.h:2969
Structure used to handle boolean flags.
Definition: utils.h:199

References ast_bridge_features_ds_get(), ast_channel_lock, ast_channel_unlock, and dtmf_features_flags_to_string().

Referenced by func_channel_read().

◆ ast_bridge_features_ds_set()

int ast_bridge_features_ds_set ( struct ast_channel chan,
struct ast_flags flags 
)

Set basic bridge DTMF feature flags datastore on the channel.

Since
12.0.0
Parameters
chanChannel to set DTMF features datastore.
flagsBuiltin DTMF feature flags. (ast_bridge_config flags)
Note
The channel must be locked before calling this function.
Return values
0on success.
-1on error.

Definition at line 258 of file bridge_basic.c.

259{
260 return bridge_features_ds_set_full(chan, flags, 1);
261}

References bridge_features_ds_set_full(), and ast_flags::flags.

Referenced by ast_bridge_features_ds_set_string(), parked_call_retrieve_enable_features(), and recalling_exit().

◆ ast_bridge_features_ds_set_string()

int ast_bridge_features_ds_set_string ( struct ast_channel chan,
const char *  features 
)

Sets the features a channel will use upon being bridged.

Since
12.0.0
Parameters
chanWhich channel to set features for
featuresWhich feature codes to set for the channel
Return values
0on success
-1on failure

Definition at line 189 of file bridge_basic.c.

190{
191 struct ast_flags flags = {0};
192
193 if (build_dtmf_features(&flags, features)) {
194 return -1;
195 }
196
197 ast_channel_lock(chan);
198 if (ast_bridge_features_ds_set(chan, &flags)) {
199 ast_channel_unlock(chan);
200 ast_log(LOG_ERROR, "Failed to apply features datastore for '%s' to channel '%s'\n", features, ast_channel_name(chan));
201 return -1;
202 }
203 ast_channel_unlock(chan);
204
205 return 0;
206}
#define ast_log
Definition: astobj2.c:42
static int build_dtmf_features(struct ast_flags *flags, const char *features)
Definition: bridge_basic.c:162
int ast_bridge_features_ds_set(struct ast_channel *chan, struct ast_flags *flags)
Set basic bridge DTMF feature flags datastore on the channel.
Definition: bridge_basic.c:258
const char * ast_channel_name(const struct ast_channel *chan)
#define LOG_ERROR
unsigned int flags
Definition: utils.h:200

References ast_bridge_features_ds_set(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_log, build_dtmf_features(), ast_flags::flags, and LOG_ERROR.

Referenced by func_channel_write_real().

◆ ast_bridging_init_basic()

void ast_bridging_init_basic ( void  )

Initialize the basic bridge class for use by the system.

Definition at line 3683 of file bridge_basic.c.

3684{
3685 /* Setup bridge basic subclass v_table. */
3691
3692 /*
3693 * Personality vtables don't have the same rules as
3694 * normal bridge vtables. These vtable functions are
3695 * used as alterations to the ast_bridge_basic_v_table
3696 * method functionality and are checked for NULL before
3697 * calling.
3698 */
3701
3702 personality_atxfer_v_table.name = "attended transfer";
3705
3708}
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:923
static int feature_blind_transfer(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Internal built in feature for blind transfers.
static void bridge_basic_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
Definition: bridge_basic.c:687
static void bridge_personality_atxfer_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
static void bridge_basic_destroy(struct ast_bridge *self)
Definition: bridge_basic.c:702
struct ast_bridge_methods personality_normal_v_table
static int bridge_personality_normal_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
Definition: bridge_basic.c:661
static int bridge_basic_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
Definition: bridge_basic.c:670
struct ast_bridge_methods personality_atxfer_v_table
static int bridge_personality_atxfer_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Internal built in feature for attended transfers.
@ AST_BRIDGE_BUILTIN_BLINDTRANSFER
@ AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER
int ast_bridge_features_register(enum ast_bridge_builtin_feature feature, ast_bridge_hook_callback callback, const char *dtmf)
Register a handler for a built in feature.
Definition: bridge.c:3062
ast_bridge_push_channel_fn push
Definition: bridge.h:265
const char * name
Definition: bridge.h:259
ast_bridge_destructor_fn destroy
Definition: bridge.h:261
ast_bridge_pull_channel_fn pull
Definition: bridge.h:267

References ast_bridge_base_v_table, ast_bridge_basic_v_table, AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, AST_BRIDGE_BUILTIN_BLINDTRANSFER, ast_bridge_features_register(), bridge_basic_destroy(), bridge_basic_pull(), bridge_basic_push(), bridge_personality_atxfer_pull(), bridge_personality_atxfer_push(), bridge_personality_normal_push(), ast_bridge_methods::destroy, feature_attended_transfer(), feature_blind_transfer(), ast_bridge_methods::name, NULL, personality_atxfer_v_table, personality_normal_v_table, ast_bridge_methods::pull, and ast_bridge_methods::push.

Referenced by ast_bridging_init().

◆ attach_framehook()

static int attach_framehook ( struct attended_transfer_properties props,
struct ast_channel channel 
)
static

Definition at line 3118 of file bridge_basic.c.

3119{
3120 struct ast_framehook_interface target_interface = {
3122 .event_cb = transfer_target_framehook_cb,
3125 .disable_inheritance = 1,
3126 };
3127
3128 ao2_ref(props, +1);
3129 target_interface.data = props;
3130
3131 ast_channel_lock(channel);
3132 props->target_framehook_id = ast_framehook_attach(channel, &target_interface);
3133 ast_channel_unlock(channel);
3134 if (props->target_framehook_id == -1) {
3135 ao2_ref(props, -1);
3136 return -1;
3137 }
3138 return 0;
3139}
static void transfer_target_framehook_destroy_cb(void *data)
static struct ast_frame * transfer_target_framehook_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
Frame hook for transfer target channel.
static int transfer_target_framehook_consume(void *data, enum ast_frame_type type)
Callback function which informs upstream if we are consuming a frame of a specific type.
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227

References ao2_ref, ast_channel_lock, ast_channel_unlock, ast_framehook_attach(), AST_FRAMEHOOK_INTERFACE_VERSION, ast_framehook_interface::data, attended_transfer_properties::target_framehook_id, transfer_target_framehook_cb(), transfer_target_framehook_consume(), transfer_target_framehook_destroy_cb(), and ast_framehook_interface::version.

Referenced by feature_attended_transfer(), and retransfer_enter().

◆ attended_transfer_monitor_thread()

static void * attended_transfer_monitor_thread ( void *  data)
static

The main loop for the attended transfer monitor thread.

This loop runs continuously until the attended transfer reaches a terminal state. Stimuli for changes in the attended transfer state are handled in this thread so that all factors in an attended transfer can be handled in an orderly fashion.

Parameters
dataThe attended transfer properties

Definition at line 3064 of file bridge_basic.c.

3065{
3066 struct attended_transfer_properties *props = data;
3067 ast_callid callid;
3068
3069 /*
3070 * Set thread callid to the transferer's callid because we
3071 * are doing all this on that channel's behalf.
3072 */
3074 callid = ast_channel_callid(props->transferer);
3076 if (callid) {
3078 }
3079
3080 for (;;) {
3081 enum attended_transfer_stimulus stimulus;
3082
3083 ast_debug(1, "About to enter state %s for attended transfer %p\n", state_properties[props->state].state_name, props);
3084
3085 if (state_properties[props->state].enter &&
3086 state_properties[props->state].enter(props)) {
3087 ast_log(LOG_ERROR, "State %s enter function returned an error for attended transfer %p\n",
3088 state_properties[props->state].state_name, props);
3089 break;
3090 }
3091
3093 ast_debug(1, "State %s is a terminal state. Ending attended transfer %p\n",
3094 state_properties[props->state].state_name, props);
3095 break;
3096 }
3097
3098 stimulus = wait_for_stimulus(props);
3099
3100 ast_debug(1, "Received stimulus %s on attended transfer %p\n", stimulus_strs[stimulus], props);
3101
3103
3104 props->state = state_properties[props->state].exit(props, stimulus);
3105
3106 ast_debug(1, "Told to enter state %s exit on attended transfer %p\n", state_properties[props->state].state_name, props);
3107 }
3108
3110
3111 if (callid) {
3113 }
3114
3115 return NULL;
3116}
static void attended_transfer_properties_shutdown(struct attended_transfer_properties *props)
Initiate shutdown of attended transfer properties.
attended_transfer_stimulus
Stimuli that can cause transfer state changes.
static const struct attended_transfer_state_properties state_properties[]
const char * stimulus_strs[]
String representations of the various stimuli.
static enum attended_transfer_stimulus wait_for_stimulus(struct attended_transfer_properties *props)
ast_callid ast_channel_callid(const struct ast_channel *chan)
#define ast_debug(level,...)
Log a DEBUG message.
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:2320
unsigned int ast_callid
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
Definition: logger.c:2339
Collection of data related to an attended transfer attempt.
enum attended_transfer_state state
struct ast_channel * transferer
enum attended_transfer_state(* exit)(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
enum attended_transfer_state_flags flags
int(* enter)(struct attended_transfer_properties *props)
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_callid_threadassoc_add(), ast_callid_threadassoc_remove(), ast_channel_callid(), ast_channel_lock, ast_channel_unlock, ast_debug, ast_log, attended_transfer_properties_shutdown(), attended_transfer_state_properties::enter, attended_transfer_state_properties::exit, attended_transfer_state_properties::flags, LOG_ERROR, NULL, attended_transfer_properties::state, attended_transfer_state_properties::state_name, state_properties, stimulus_strs, TRANSFER_STATE_FLAG_TERMINAL, attended_transfer_properties::transferer, and wait_for_stimulus().

Referenced by feature_attended_transfer().

◆ attended_transfer_properties_alloc()

static struct attended_transfer_properties * attended_transfer_properties_alloc ( struct ast_channel transferer,
const char *  context 
)
static

Allocate and initialize attended transfer properties.

Parameters
transfererThe channel performing the attended transfer
contextSuggestion for what context the transfer target extension can be found in
Return values
NULLFailure to allocate or initialize
non-NULLNewly allocated properties

Definition at line 1425 of file bridge_basic.c.

1427{
1428 struct attended_transfer_properties *props;
1429 char *tech;
1430 char *addr;
1431 char *serial;
1432 struct ast_features_xfer_config *xfer_cfg;
1433 struct ast_flags *transferer_features;
1434
1435 props = ao2_alloc(sizeof(*props), attended_transfer_properties_destructor);
1436 if (!props) {
1437 ast_log(LOG_ERROR, "Unable to create props - channel %s, context %s\n",
1438 ast_channel_name(transferer), context);
1439 return NULL;
1440 }
1441
1442 ast_cond_init(&props->cond, NULL);
1443
1444 if (ast_string_field_init(props, 64)) {
1445 ast_log(LOG_ERROR, "Unable to initialize prop fields - channel %s, context %s\n",
1446 ast_channel_name(transferer), context);
1447 ao2_ref(props, -1);
1448 return NULL;
1449 }
1450
1451 props->target_framehook_id = -1;
1452 props->transferer = ast_channel_ref(transferer);
1453
1456 if (!xfer_cfg) {
1457 ast_log(LOG_ERROR, "Unable to get transfer configuration from channel %s\n", ast_channel_name(props->transferer));
1459 ao2_ref(props, -1);
1460 return NULL;
1461 }
1462 transferer_features = ast_bridge_features_ds_get(props->transferer);
1463 if (transferer_features) {
1464 props->transferer_features = *transferer_features;
1465 }
1466 props->atxferdropcall = xfer_cfg->atxferdropcall;
1469 props->atxferloopdelay = xfer_cfg->atxferloopdelay;
1471 ast_string_field_set(props, xfersound, xfer_cfg->xfersound);
1472 ao2_ref(xfer_cfg, -1);
1473
1474 /*
1475 * Save the transferee's party information for any recall calls.
1476 * This is the only piece of information needed that gets overwritten
1477 * on the transferer channel by the inital call to the transfer target.
1478 */
1481
1482 tech = ast_strdupa(ast_channel_name(props->transferer));
1483 addr = strchr(tech, '/');
1484 if (!addr) {
1485 ast_log(LOG_ERROR, "Transferer channel name does not follow typical channel naming format (tech/address)\n");
1487 ao2_ref(props, -1);
1488 return NULL;
1489 }
1490 *addr++ = '\0';
1491 serial = strrchr(addr, '-');
1492 if (serial) {
1493 *serial = '\0';
1494 }
1495 ast_string_field_set(props, transferer_type, tech);
1496 ast_string_field_set(props, transferer_addr, addr);
1497
1499
1500 ast_debug(1, "Allocated attended transfer properties %p for transfer from %s\n",
1501 props, ast_channel_name(props->transferer));
1502 return props;
1503}
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
static void attended_transfer_properties_destructor(void *obj)
static const char * get_transfer_context(struct ast_channel *transferer, const char *context)
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:2050
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2993
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
struct ast_party_connected_line original_transferer_colp
struct ast_flags transferer_features

References ao2_alloc, ao2_ref, ast_bridge_features_ds_get(), ast_channel_connected(), ast_channel_lock, ast_channel_name(), ast_channel_ref, ast_channel_unlock, ast_cond_init, ast_debug, ast_get_chan_features_xfer_config(), ast_log, ast_party_connected_line_copy(), ast_strdupa, ast_string_field_init, ast_string_field_set, attended_transfer_properties_destructor(), ast_features_xfer_config::atxfercallbackretries, attended_transfer_properties::atxfercallbackretries, ast_features_xfer_config::atxferdropcall, attended_transfer_properties::atxferdropcall, ast_features_xfer_config::atxferloopdelay, attended_transfer_properties::atxferloopdelay, ast_features_xfer_config::atxfernoanswertimeout, attended_transfer_properties::atxfernoanswertimeout, attended_transfer_properties::cond, voicemailpwcheck::context, get_transfer_context(), LOG_ERROR, NULL, attended_transfer_properties::original_transferer_colp, attended_transfer_properties::target_framehook_id, attended_transfer_properties::transferer, attended_transfer_properties::transferer_features, and ast_features_xfer_config::xfersound.

Referenced by feature_attended_transfer().

◆ attended_transfer_properties_destructor()

static void attended_transfer_properties_destructor ( void *  obj)
static

Definition at line 1352 of file bridge_basic.c.

1353{
1354 struct attended_transfer_properties *props = obj;
1355
1356 ast_debug(1, "Destroy attended transfer properties %p\n", props);
1357
1358 ao2_cleanup(props->target_bridge);
1360 /* Use ast_channel_cleanup() instead of ast_channel_unref() for channels since they may be NULL */
1366 ast_cond_destroy(&props->cond);
1367}
#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:2091
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3015
#define ast_cond_destroy(cond)
Definition: lock.h:202
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
struct ast_bridge * transferee_bridge
struct ast_channel * recall_target
struct ast_bridge * target_bridge
struct ast_channel * transfer_target

References ao2_cleanup, ast_channel_cleanup, ast_cond_destroy, ast_debug, ast_party_connected_line_free(), ast_string_field_free_memory, attended_transfer_properties::cond, attended_transfer_properties::original_transferer_colp, attended_transfer_properties::recall_target, attended_transfer_properties::target_bridge, attended_transfer_properties::transfer_target, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer.

Referenced by attended_transfer_properties_alloc().

◆ attended_transfer_properties_shutdown()

static void attended_transfer_properties_shutdown ( struct attended_transfer_properties props)
static

Initiate shutdown of attended transfer properties.

Calling this indicates that the attended transfer properties are no longer needed because the transfer operation has concluded.

Definition at line 1524 of file bridge_basic.c.

1525{
1526 ast_debug(1, "Shutting down attended transfer %p\n", props);
1527
1528 if (props->transferee_bridge) {
1532 }
1533
1534 if (props->target_bridge) {
1536 props->target_bridge = NULL;
1537 }
1538
1539 if (props->transferer) {
1541 }
1542
1543 clear_stimulus_queue(props);
1544
1545 ao2_cleanup(props);
1546}
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:944
void ast_bridge_merge_inhibit(struct ast_bridge *bridge, int request)
Adjust the bridge merge inhibit request count.
Definition: bridge.c:3000
static void bridge_basic_change_personality(struct ast_bridge *bridge, enum bridge_basic_personality_type type, void *user_data)
Change basic bridge personality.
static void clear_stimulus_queue(struct attended_transfer_properties *props)
Free backlog of stimuli in the queue.
void ast_channel_remove_bridge_role(struct ast_channel *chan, const char *role_name)
Removes a bridge role from a channel.
Definition: bridge_roles.c:332

References ao2_cleanup, ast_bridge_destroy(), ast_bridge_merge_inhibit(), ast_channel_remove_bridge_role(), ast_debug, AST_TRANSFERER_ROLE_NAME, bridge_basic_change_personality(), BRIDGE_BASIC_PERSONALITY_NORMAL, clear_stimulus_queue(), NULL, attended_transfer_properties::target_bridge, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer.

Referenced by attended_transfer_monitor_thread(), and feature_attended_transfer().

◆ atxfer_abort()

static int atxfer_abort ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

DTMF hook when transferer presses abort sequence.

Sends a stimulus to the attended transfer monitor thread that the abort sequence has been pressed

Definition at line 2761 of file bridge_basic.c.

2762{
2763 struct attended_transfer_properties *props = hook_pvt;
2764
2765 ast_debug(1, "Transferer on attended transfer %p pressed abort sequence\n", props);
2767 return 0;
2768}
static void stimulate_attended_transfer(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)

References ast_debug, stimulate_attended_transfer(), and STIMULUS_DTMF_ATXFER_ABORT.

Referenced by add_transferer_role(), and bridge_personality_atxfer_push().

◆ atxfer_complete()

static int atxfer_complete ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

DTMF hook when transferer presses complete sequence.

Sends a stimulus to the attended transfer monitor thread that the complete sequence has been pressed

Definition at line 2775 of file bridge_basic.c.

2776{
2777 struct attended_transfer_properties *props = hook_pvt;
2778
2779 ast_debug(1, "Transferer on attended transfer %p pressed complete sequence\n", props);
2781 return 0;
2782}

References ast_debug, stimulate_attended_transfer(), and STIMULUS_DTMF_ATXFER_COMPLETE.

Referenced by add_transferer_role(), and bridge_personality_atxfer_push().

◆ atxfer_swap()

static int atxfer_swap ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

DTMF hook when transferer presses swap sequence.

Sends a stimulus to the attended transfer monitor thread that the swap sequence has been pressed

Definition at line 2803 of file bridge_basic.c.

2804{
2805 struct attended_transfer_properties *props = hook_pvt;
2806
2807 ast_debug(1, "Transferer on attended transfer %p pressed swap sequence\n", props);
2809 return 0;
2810}

References ast_debug, stimulate_attended_transfer(), and STIMULUS_DTMF_ATXFER_SWAP.

Referenced by add_transferer_role(), and bridge_personality_atxfer_push().

◆ atxfer_threeway()

static int atxfer_threeway ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

DTMF hook when transferer presses threeway sequence.

Sends a stimulus to the attended transfer monitor thread that the threeway sequence has been pressed

Definition at line 2789 of file bridge_basic.c.

2790{
2791 struct attended_transfer_properties *props = hook_pvt;
2792
2793 ast_debug(1, "Transferer on attended transfer %p pressed threeway sequence\n", props);
2795 return 0;
2796}

References ast_debug, stimulate_attended_transfer(), and STIMULUS_DTMF_ATXFER_THREEWAY.

Referenced by add_transferer_role(), and bridge_personality_atxfer_push().

◆ atxfer_transferer_hangup()

static int atxfer_transferer_hangup ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

Hangup hook for transferer channel.

Sends a stimulus to the attended transfer monitor thread that the transferer has hung up.

Definition at line 2817 of file bridge_basic.c.

2818{
2819 struct attended_transfer_properties *props = hook_pvt;
2820
2821 ast_debug(1, "Transferer on attended transfer %p hung up\n", props);
2823 return 0;
2824}

References ast_debug, stimulate_attended_transfer(), and STIMULUS_TRANSFERER_HANGUP.

Referenced by bridge_personality_atxfer_push().

◆ basic_hangup_hook()

static int basic_hangup_hook ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

Definition at line 290 of file bridge_basic.c.

291{
292 int bridge_count = 0;
293 struct ast_bridge_channel *iter;
294
295 ast_bridge_channel_lock_bridge(bridge_channel);
296 AST_LIST_TRAVERSE(&bridge_channel->bridge->channels, iter, entry) {
297 if (iter != bridge_channel && iter->state == BRIDGE_CHANNEL_STATE_WAIT) {
298 ++bridge_count;
299 }
300 }
301 if (2 <= bridge_count) {
302 /* Just allow this channel to leave the multi-party bridge. */
303 ast_bridge_channel_leave_bridge(bridge_channel,
305 }
306 ast_bridge_unlock(bridge_channel->bridge);
307 return 0;
308}
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
Lock the bridge associated with the bridge channel.
@ BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE
@ BRIDGE_CHANNEL_STATE_WAIT
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_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 * bridge
Bridge this channel is participating in.
enum bridge_channel_state state
struct ast_bridge_channels_list channels
Definition: bridge.h:363
Definition: search.h:40

References ast_bridge_channel_leave_bridge(), ast_bridge_channel_lock_bridge(), ast_bridge_unlock, AST_LIST_TRAVERSE, ast_bridge_channel::bridge, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, BRIDGE_CHANNEL_STATE_WAIT, ast_bridge::channels, and ast_bridge_channel::state.

Referenced by add_normal_hooks().

◆ blind_transfer_cb()

static void blind_transfer_cb ( struct ast_channel new_channel,
struct transfer_channel_data user_data_wrapper,
enum ast_transfer_type  transfer_type 
)
static

Definition at line 3505 of file bridge_basic.c.

3507{
3508 struct ast_channel *transferer_channel = user_data_wrapper->data;
3509
3510 if (transfer_type == AST_BRIDGE_TRANSFER_MULTI_PARTY) {
3511 copy_caller_data(new_channel, transferer_channel);
3512 }
3513}
@ AST_BRIDGE_TRANSFER_MULTI_PARTY
Definition: bridge.h:1113
static void copy_caller_data(struct ast_channel *dest, struct ast_channel *caller)
Main Channel structure associated with a channel.

References AST_BRIDGE_TRANSFER_MULTI_PARTY, copy_caller_data(), and transfer_channel_data::data.

Referenced by feature_blind_transfer().

◆ blond_enter()

static int blond_enter ( struct attended_transfer_properties props)
static

Definition at line 2344 of file bridge_basic.c.

2345{
2346 struct ast_channel *transferee_channel;
2347 struct ast_channel *target_channel;
2348
2350 &transferee_channel, &target_channel);
2351 bridge_merge(props->transferee_bridge, props->target_bridge, &props->transferer, 1);
2352 ringing(props->transfer_target);
2353 publish_transfer_success(props, transferee_channel, target_channel);
2354
2355 ast_channel_cleanup(transferee_channel);
2356 ast_channel_cleanup(target_channel);
2357 return 0;
2358}
static void ringing(struct ast_channel *chan)
Helper method to send a ringing indication to a channel in a bridge.
static void get_transfer_parties(struct ast_channel *transferer, struct ast_bridge *transferee_bridge, struct ast_bridge *target_bridge, struct ast_channel **transferee, struct ast_channel **transfer_target)
determine transferee and transfer target for an attended transfer
static void publish_transfer_success(struct attended_transfer_properties *props, struct ast_channel *transferee_channel, struct ast_channel *target_channel)
Send a stasis publication for a successful attended transfer.
static void bridge_merge(struct ast_bridge *dest, struct ast_bridge *src, struct ast_channel **kick_channels, unsigned int num_channels)
Wrapper for bridge_do_merge.

References ast_channel_cleanup, bridge_merge(), get_transfer_parties(), publish_transfer_success(), ringing(), attended_transfer_properties::target_bridge, attended_transfer_properties::transfer_target, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer.

Referenced by blond_nonfinal_enter().

◆ blond_nonfinal_enter()

static int blond_nonfinal_enter ( struct attended_transfer_properties props)
static

Definition at line 2360 of file bridge_basic.c.

2361{
2362 int res;
2364 /* move the transfer target to the recall target along with its reference */
2366 res = blond_enter(props);
2368 return res;
2369}
static int blond_enter(struct attended_transfer_properties *props)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
enum attended_transfer_superstate superstate

References ast_channel_ref, ast_channel_unref, blond_enter(), attended_transfer_properties::recall_target, attended_transfer_properties::superstate, SUPERSTATE_RECALL, and attended_transfer_properties::transfer_target.

◆ blond_nonfinal_exit()

static enum attended_transfer_state blond_nonfinal_exit ( struct attended_transfer_properties props,
enum attended_transfer_stimulus  stimulus 
)
static

Definition at line 2371 of file bridge_basic.c.

2373{
2374 switch (stimulus) {
2376 return TRANSFER_FAIL;
2378 return TRANSFER_RESUME;
2379 case STIMULUS_TIMEOUT:
2381 /* It is possible before we hung them up that they queued up a recall target answer
2382 * so we remove it if present as it should not exist.
2383 */
2387 return TRANSFER_RECALLING;
2388 case STIMULUS_NONE:
2396 default:
2397 ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2398 stimulus_strs[stimulus], state_properties[props->state].state_name);
2399 return props->state;
2400 }
2401}
static void remove_attended_transfer_stimulus(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2490
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1168
#define LOG_WARNING

References ast_channel_unref, ast_log, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, LOG_WARNING, attended_transfer_properties::recall_target, remove_attended_transfer_stimulus(), attended_transfer_properties::state, attended_transfer_state_properties::state_name, state_properties, STIMULUS_DTMF_ATXFER_ABORT, STIMULUS_DTMF_ATXFER_COMPLETE, STIMULUS_DTMF_ATXFER_SWAP, STIMULUS_DTMF_ATXFER_THREEWAY, STIMULUS_NONE, STIMULUS_RECALL_TARGET_ANSWER, STIMULUS_RECALL_TARGET_HANGUP, stimulus_strs, STIMULUS_TIMEOUT, STIMULUS_TRANSFER_TARGET_ANSWER, STIMULUS_TRANSFER_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, STIMULUS_TRANSFERER_HANGUP, TRANSFER_FAIL, TRANSFER_RECALLING, and TRANSFER_RESUME.

◆ bridge_basic_change_personality()

static void bridge_basic_change_personality ( struct ast_bridge bridge,
enum bridge_basic_personality_type  type,
void *  user_data 
)
static

Change basic bridge personality.

Changing personalities allows for the bridge to remain in use but have properties such as its v_table and its flags change.

Parameters
bridgeThe bridge
typeThe personality to change the bridge to
user_dataPrivate data to attach to the personality.

Definition at line 3574 of file bridge_basic.c.

3576{
3577 struct bridge_basic_personality *personality = bridge->personality;
3579
3581
3582 ao2_cleanup(personality->details[personality->current].pvt);
3583 personality->details[personality->current].pvt = NULL;
3585
3586 personality->current = type;
3587 if (user_data) {
3588 ao2_ref(user_data, +1);
3589 }
3590 personality->details[personality->current].pvt = user_data;
3591 ast_set_flag(&bridge->feature_flags, personality->details[personality->current].bridge_flags);
3592 if (personality->details[personality->current].on_personality_change) {
3593 personality->details[personality->current].on_personality_change(bridge);
3594 }
3595}
static void remove_hooks_on_personality_change(struct ast_bridge *bridge)
Remove appropriate hooks when basic bridge personality changes.
Definition: bridge_basic.c:719
static const char type[]
Definition: chan_ooh323.c:109
void(* on_personality_change)(struct ast_bridge *bridge)
Definition: bridge_basic.c:321
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define AST_FLAGS_ALL
Definition: utils.h:196

References ao2_cleanup, ao2_ref, ast_bridge_lock, ast_bridge_unlock, ast_clear_flag, AST_FLAGS_ALL, ast_set_flag, personality_details::bridge_flags, bridge_basic_personality::current, bridge_basic_personality::details, ast_bridge::feature_flags, lock, NULL, personality_details::on_personality_change, ast_bridge::personality, personality_details::pvt, remove_hooks_on_personality_change(), SCOPED_LOCK, and type.

Referenced by attended_transfer_properties_shutdown(), consulting_exit(), and feature_attended_transfer().

◆ bridge_basic_destroy()

static void bridge_basic_destroy ( struct ast_bridge self)
static

Definition at line 702 of file bridge_basic.c.

703{
704 struct bridge_basic_personality *personality = self->personality;
705
706 ao2_cleanup(personality);
707
709}

References ao2_cleanup, ast_bridge_base_v_table, ast_bridge_methods::destroy, and ast_bridge::personality.

Referenced by ast_bridging_init_basic().

◆ bridge_basic_personality_alloc()

static struct ast_bridge * bridge_basic_personality_alloc ( struct ast_bridge bridge)
static

Definition at line 3638 of file bridge_basic.c.

3639{
3640 struct bridge_basic_personality *personality;
3641 int i;
3642
3643 if (!bridge) {
3644 return NULL;
3645 }
3646
3647 personality = ao2_alloc(sizeof(*personality), personality_destructor);
3648 if (!personality) {
3649 ao2_ref(bridge, -1);
3650 return NULL;
3651 }
3652 for (i = 0; i < BRIDGE_BASIC_PERSONALITY_END; ++i) {
3653 init_details(&personality->details[i], i);
3654 }
3656 bridge->personality = personality;
3657
3658 return bridge;
3659}
static void init_details(struct personality_details *details, enum bridge_basic_personality_type type)
static void personality_destructor(void *obj)

References ao2_alloc, ao2_ref, BRIDGE_BASIC_PERSONALITY_END, BRIDGE_BASIC_PERSONALITY_NORMAL, bridge_basic_personality::current, bridge_basic_personality::details, init_details(), NULL, ast_bridge::personality, and personality_destructor().

Referenced by ast_bridge_basic_new().

◆ bridge_basic_pull()

static void bridge_basic_pull ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 687 of file bridge_basic.c.

688{
689 struct bridge_basic_personality *personality = self->personality;
690
691 ast_assert(personality != NULL);
692
693 if (personality->details[personality->current].v_table->pull) {
694 personality->details[personality->current].v_table->pull(self, bridge_channel);
695 }
696
698
699 ast_bridge_base_v_table.pull(self, bridge_channel);
700}
void ast_bridge_channel_update_accountcodes(struct ast_bridge_channel *joining, struct ast_bridge_channel *leaving)
struct ast_bridge_methods * v_table
Definition: bridge_basic.c:315

References ast_assert, ast_bridge_base_v_table, ast_bridge_channel_update_accountcodes(), bridge_basic_personality::current, bridge_basic_personality::details, NULL, ast_bridge::personality, ast_bridge_methods::pull, and personality_details::v_table.

Referenced by ast_bridging_init_basic().

◆ bridge_basic_push()

static int bridge_basic_push ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel,
struct ast_bridge_channel swap 
)
static

Definition at line 670 of file bridge_basic.c.

671{
672 struct bridge_basic_personality *personality = self->personality;
673
674 ast_assert(personality != NULL);
675
676 if (personality->details[personality->current].v_table->push
677 && personality->details[personality->current].v_table->push(self, bridge_channel, swap)) {
678 return -1;
679 }
680
681 ast_bridge_channel_update_linkedids(bridge_channel, swap);
682 ast_bridge_channel_update_accountcodes(bridge_channel, swap);
683
684 return ast_bridge_base_v_table.push(self, bridge_channel, swap);
685}
void ast_bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)

References ast_assert, ast_bridge_base_v_table, ast_bridge_channel_update_accountcodes(), ast_bridge_channel_update_linkedids(), bridge_basic_personality::current, bridge_basic_personality::details, NULL, ast_bridge::personality, ast_bridge_methods::push, and personality_details::v_table.

Referenced by ast_bridging_init_basic().

◆ bridge_basic_setup_features()

static int bridge_basic_setup_features ( struct ast_bridge_channel bridge_channel)
static

Definition at line 630 of file bridge_basic.c.

631{
632 int res = 0;
633
634 res |= setup_bridge_features_builtin(bridge_channel->features, bridge_channel->chan);
635 res |= setup_bridge_features_dynamic(bridge_channel->features, bridge_channel->chan);
636
637 return res;
638}
static int setup_bridge_features_dynamic(struct ast_bridge_features *features, struct ast_channel *chan)
Definition: bridge_basic.c:604
static int setup_bridge_features_builtin(struct ast_bridge_features *features, struct ast_channel *chan)
Definition: bridge_basic.c:400
struct ast_channel * chan

References ast_bridge_channel::chan, ast_bridge_channel::features, setup_bridge_features_builtin(), and setup_bridge_features_dynamic().

Referenced by add_normal_hooks().

◆ bridge_features_ds_set_full()

static int bridge_features_ds_set_full ( struct ast_channel chan,
struct ast_flags flags,
int  replace 
)
static

Definition at line 224 of file bridge_basic.c.

225{
226 struct ast_datastore *datastore;
227 struct ast_flags *ds_flags;
228
230 if (datastore) {
231 ds_flags = datastore->data;
232 if (replace) {
233 *ds_flags = *flags;
234 } else {
235 flags->flags = flags->flags | ds_flags->flags;
236 *ds_flags = *flags;
237 }
238 return 0;
239 }
240
242 if (!datastore) {
243 return -1;
244 }
245
246 ds_flags = ast_malloc(sizeof(*ds_flags));
247 if (!ds_flags) {
248 ast_datastore_free(datastore);
249 return -1;
250 }
251
252 *ds_flags = *flags;
253 datastore->data = ds_flags;
254 ast_channel_datastore_add(chan, datastore);
255 return 0;
256}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2404
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:888

References ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_malloc, ast_datastore::data, dtmf_features_info, ast_flags::flags, NULL, and replace().

Referenced by ast_bridge_features_ds_append(), and ast_bridge_features_ds_set().

◆ bridge_hold()

static void bridge_hold ( struct ast_bridge bridge)
static

Helper method to send a hold frame to all channels in a bridge.

Definition at line 1862 of file bridge_basic.c.

1863{
1864 struct ast_frame hold = {
1865 .frametype = AST_FRAME_CONTROL,
1866 .subclass.integer = AST_CONTROL_HOLD,
1867 };
1868
1869 ast_bridge_lock(bridge);
1871 ast_bridge_unlock(bridge);
1872}
int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
Queue the given frame to everyone else.
static void hold(struct ast_channel *chan)
Helper method to place a channel in a bridge on hold.
@ AST_FRAME_CONTROL
@ AST_CONTROL_HOLD
Data structure associated with a single frame of data.

References ast_bridge_lock, ast_bridge_queue_everyone_else(), ast_bridge_unlock, AST_CONTROL_HOLD, AST_FRAME_CONTROL, hold(), and NULL.

Referenced by wait_to_recall_enter(), and wait_to_retransfer_enter().

◆ bridge_merge()

static void bridge_merge ( struct ast_bridge dest,
struct ast_bridge src,
struct ast_channel **  kick_channels,
unsigned int  num_channels 
)
static

Wrapper for bridge_do_merge.

Definition at line 1919 of file bridge_basic.c.

1920{
1921 struct ast_bridge_channel **kick_bridge_channels = num_channels ?
1922 ast_alloca(num_channels * sizeof(*kick_bridge_channels)) : NULL;
1923 int i;
1924 int num_bridge_channels = 0;
1925
1926 ast_bridge_lock_both(dest, src);
1927
1928 for (i = 0; i < num_channels; ++i) {
1929 struct ast_bridge_channel *kick_bridge_channel;
1930
1931 kick_bridge_channel = bridge_find_channel(src, kick_channels[i]);
1932 if (!kick_bridge_channel) {
1933 kick_bridge_channel = bridge_find_channel(dest, kick_channels[i]);
1934 }
1935
1936 /* It's possible (and fine) for the bridge channel to be NULL at this point if the
1937 * channel has hung up already. If that happens, we can just remove it from the list
1938 * of bridge channels to kick from the bridge
1939 */
1940 if (!kick_bridge_channel) {
1941 continue;
1942 }
1943
1944 kick_bridge_channels[num_bridge_channels++] = kick_bridge_channel;
1945 }
1946
1947 bridge_do_merge(dest, src, kick_bridge_channels, num_bridge_channels, 0);
1948 ast_bridge_unlock(dest);
1949 ast_bridge_unlock(src);
1950}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_bridge_lock_both(bridge1, bridge2)
Lock two bridges.
Definition: bridge.h:488
void bridge_do_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_bridge_channel **kick_me, unsigned int num_kick, unsigned int optimized)
Definition: bridge.c:2048
struct ast_bridge_channel * bridge_find_channel(struct ast_bridge *bridge, struct ast_channel *chan)
Definition: bridge.c:1429

References ast_alloca, ast_bridge_lock_both, ast_bridge_unlock, bridge_do_merge(), bridge_find_channel(), and NULL.

Referenced by blond_enter(), complete_enter(), and threeway_enter().

◆ bridge_move()

static void bridge_move ( struct ast_bridge dest,
struct ast_bridge src,
struct ast_channel channel,
struct ast_channel swap 
)
static

Wrapper for bridge_do_move.

Definition at line 1892 of file bridge_basic.c.

1893{
1894 struct ast_bridge_channel *bridge_channel;
1895
1896 ast_bridge_lock_both(src, dest);
1897
1898 ast_channel_lock(channel);
1899 bridge_channel = ast_channel_get_bridge_channel(channel);
1900 ast_channel_unlock(channel);
1901
1902 if (bridge_channel) {
1903 ao2_lock(bridge_channel);
1904 bridge_channel->swap = swap;
1905 ao2_unlock(bridge_channel);
1906
1907 bridge_do_move(dest, bridge_channel, 1, 0);
1908 }
1909
1910 ast_bridge_unlock(dest);
1911 ast_bridge_unlock(src);
1912
1913 ao2_cleanup(bridge_channel);
1914}
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
int bridge_do_move(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bridge_channel, int attempt_recovery, unsigned int optimized)
Definition: bridge.c:2314
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:10604
struct ast_channel * swap

References ao2_cleanup, ao2_lock, ao2_unlock, ast_bridge_lock_both, ast_bridge_unlock, ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, bridge_do_move(), and ast_bridge_channel::swap.

Referenced by calling_target_enter(), consulting_exit(), double_checking_exit(), hesitant_enter(), and rebridge_enter().

◆ bridge_personality_atxfer_pull()

static void bridge_personality_atxfer_pull ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 3000 of file bridge_basic.c.

3001{
3002 struct bridge_basic_personality *personality = self->personality;
3003 struct attended_transfer_properties *props = personality->details[personality->current].pvt;
3004
3005 switch (props->superstate) {
3007 transfer_pull(self, bridge_channel, props);
3008 break;
3009 case SUPERSTATE_RECALL:
3010 recall_pull(self, bridge_channel, props);
3011 break;
3012 }
3013}
static void recall_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct attended_transfer_properties *props)
static void transfer_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct attended_transfer_properties *props)

References bridge_basic_personality::current, bridge_basic_personality::details, ast_bridge::personality, personality_details::pvt, recall_pull(), attended_transfer_properties::superstate, SUPERSTATE_RECALL, SUPERSTATE_TRANSFER, and transfer_pull().

Referenced by ast_bridging_init_basic().

◆ bridge_personality_atxfer_push()

static int bridge_personality_atxfer_push ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel,
struct ast_bridge_channel swap 
)
static

Definition at line 2875 of file bridge_basic.c.

2876{
2877 const char *abort_dtmf;
2878 const char *complete_dtmf;
2879 const char *threeway_dtmf;
2880 const char *swap_dtmf;
2881 struct bridge_basic_personality *personality = self->personality;
2882
2883 if (!ast_channel_has_role(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME)) {
2884 return 0;
2885 }
2886
2887 abort_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "abort");
2888 complete_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "complete");
2889 threeway_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "threeway");
2890 swap_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "swap");
2891
2892 if (!ast_strlen_zero(abort_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2893 abort_dtmf, atxfer_abort, personality->details[personality->current].pvt, NULL,
2895 return -1;
2896 }
2897 if (!ast_strlen_zero(complete_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2898 complete_dtmf, atxfer_complete, personality->details[personality->current].pvt, NULL,
2900 return -1;
2901 }
2902 if (!ast_strlen_zero(threeway_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2903 threeway_dtmf, atxfer_threeway, personality->details[personality->current].pvt, NULL,
2905 return -1;
2906 }
2907 if (!ast_strlen_zero(swap_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2908 swap_dtmf, atxfer_swap, personality->details[personality->current].pvt, NULL,
2910 return -1;
2911 }
2913 personality->details[personality->current].pvt, NULL,
2915 return -1;
2916 }
2917
2918 return 0;
2919}
static int atxfer_transferer_hangup(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Hangup hook for transferer channel.
@ AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE
int ast_bridge_dtmf_hook(struct ast_bridge_features *features, const char *dtmf, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a DTMF hook to a bridge features structure.
Definition: bridge.c:3182
const char * ast_channel_get_role_option(struct ast_channel *channel, const char *role_name, const char *option)
Retrieve the value of a requested role option from a channel.
Definition: bridge_roles.c:399
int ast_channel_has_role(struct ast_channel *channel, const char *role_name)
Check if a role exists on a channel.
Definition: bridge_roles.c:394
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

References ast_bridge_dtmf_hook(), ast_bridge_hangup_hook(), AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE, AST_BRIDGE_HOOK_REMOVE_ON_PULL, ast_channel_get_role_option(), ast_channel_has_role(), ast_strlen_zero(), AST_TRANSFERER_ROLE_NAME, atxfer_abort(), atxfer_complete(), atxfer_swap(), atxfer_threeway(), atxfer_transferer_hangup(), ast_bridge_channel::chan, bridge_basic_personality::current, bridge_basic_personality::details, ast_bridge_channel::features, NULL, ast_bridge::personality, and personality_details::pvt.

Referenced by ast_bridging_init_basic().

◆ bridge_personality_normal_push()

static int bridge_personality_normal_push ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel,
struct ast_bridge_channel swap 
)
static

Definition at line 661 of file bridge_basic.c.

662{
663 if (add_normal_hooks(self, bridge_channel)) {
664 return -1;
665 }
666
667 return 0;
668}
static int add_normal_hooks(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Definition: bridge_basic.c:640

References add_normal_hooks().

Referenced by ast_bridging_init_basic().

◆ bridge_ringing()

static void bridge_ringing ( struct ast_bridge bridge)
static

Helper method to send a ringing indication to all channels in a bridge.

Definition at line 1847 of file bridge_basic.c.

1848{
1849 struct ast_frame ringing = {
1850 .frametype = AST_FRAME_CONTROL,
1851 .subclass.integer = AST_CONTROL_RINGING,
1852 };
1853
1854 ast_bridge_lock(bridge);
1856 ast_bridge_unlock(bridge);
1857}
@ AST_CONTROL_RINGING

References ast_bridge_lock, ast_bridge_queue_everyone_else(), ast_bridge_unlock, AST_CONTROL_RINGING, AST_FRAME_CONTROL, NULL, and ringing().

Referenced by recalling_enter().

◆ bridge_unhold()

static void bridge_unhold ( struct ast_bridge bridge)
static

Helper method to send an unhold frame to all channels in a bridge.

Definition at line 1877 of file bridge_basic.c.

1878{
1879 struct ast_frame unhold = {
1880 .frametype = AST_FRAME_CONTROL,
1881 .subclass.integer = AST_CONTROL_UNHOLD,
1882 };
1883
1884 ast_bridge_lock(bridge);
1886 ast_bridge_unlock(bridge);
1887}
static void unhold(struct ast_channel *chan)
Helper method to take a channel in a bridge off hold.
@ AST_CONTROL_UNHOLD

References ast_bridge_lock, ast_bridge_queue_everyone_else(), ast_bridge_unlock, AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, NULL, and unhold().

Referenced by calling_target_exit(), consulting_exit(), double_checking_exit(), wait_to_recall_exit(), and wait_to_retransfer_exit().

◆ build_dtmf_features()

static int build_dtmf_features ( struct ast_flags flags,
const char *  features 
)
static

Definition at line 162 of file bridge_basic.c.

163{
164 const char *feature;
165
166 char missing_features[strlen(features) + 1];
167 size_t number_of_missing_features = 0;
168
169 for (feature = features; *feature; feature++) {
170 if (!isupper(*feature)) {
171 ast_log(LOG_ERROR, "Features string '%s' rejected because it contains non-uppercase feature.\n", features);
172 return -1;
173 }
174
175 if (set_feature_flag_from_char(flags, *feature)) {
176 missing_features[number_of_missing_features++] = *feature;
177 }
178 }
179
180 missing_features[number_of_missing_features] = '\0';
181
182 if (number_of_missing_features) {
183 ast_log(LOG_WARNING, "Features '%s' from features string '%s' can not be applied.\n", missing_features, features);
184 }
185
186 return 0;
187}
static int set_feature_flag_from_char(struct ast_flags *feature_flags, char feature)
Definition: bridge_basic.c:98

References ast_log, LOG_ERROR, LOG_WARNING, and set_feature_flag_from_char().

Referenced by ast_bridge_features_ds_set_string().

◆ builtin_feature_get_exten()

static int builtin_feature_get_exten ( struct ast_channel chan,
const char *  feature_name,
char *  buf,
size_t  len 
)
static

Definition at line 346 of file bridge_basic.c.

347{
349
350 return ast_get_builtin_feature(chan, feature_name, buf, len);
351}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_get_builtin_feature(struct ast_channel *chan, const char *feature, char *buf, size_t len)
Get the DTMF code for a builtin feature.

References ast_get_builtin_feature(), buf, len(), lock, and SCOPED_CHANNELLOCK.

Referenced by builtin_features_helper().

◆ builtin_features_helper()

static int builtin_features_helper ( struct ast_bridge_features features,
struct ast_channel chan,
struct ast_flags flags,
unsigned int  feature_flag,
const char *  feature_name,
enum ast_bridge_builtin_feature  feature_bridge 
)
static

Definition at line 368 of file bridge_basic.c.

370{
371 char dtmf[AST_FEATURE_MAX_LEN];
372 int res;
373
374 res = 0;
375 if (ast_test_flag(flags, feature_flag)
376 && !builtin_feature_get_exten(chan, feature_name, dtmf, sizeof(dtmf))
377 && !ast_strlen_zero(dtmf)) {
378 res = ast_bridge_features_enable(features, feature_bridge, dtmf, NULL, NULL,
380 if (res) {
381 ast_log(LOG_ERROR, "Channel %s: Requested DTMF feature %s not available.\n",
382 ast_channel_name(chan), feature_name);
383 }
384 }
385
386 return res;
387}
static int builtin_feature_get_exten(struct ast_channel *chan, const char *feature_name, char *buf, size_t len)
Definition: bridge_basic.c:346
int ast_bridge_features_enable(struct ast_bridge_features *features, enum ast_bridge_builtin_feature feature, const char *dtmf, void *config, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Enable a built in feature on a bridge features structure.
Definition: bridge.c:3365
#define AST_FEATURE_MAX_LEN
#define ast_test_flag(p, flag)
Definition: utils.h:63

References ast_bridge_features_enable(), AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE, AST_BRIDGE_HOOK_REMOVE_ON_PULL, ast_channel_name(), AST_FEATURE_MAX_LEN, ast_log, ast_strlen_zero(), ast_test_flag, builtin_feature_get_exten(), LOG_ERROR, and NULL.

Referenced by setup_bridge_features_builtin().

◆ calling_target_enter()

static int calling_target_enter ( struct attended_transfer_properties props)
static

Definition at line 2122 of file bridge_basic.c.

2123{
2125 return 0;
2126}
static void bridge_move(struct ast_bridge *dest, struct ast_bridge *src, struct ast_channel *channel, struct ast_channel *swap)
Wrapper for bridge_do_move.

References bridge_move(), NULL, attended_transfer_properties::target_bridge, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer.

◆ calling_target_exit()

static enum attended_transfer_state calling_target_exit ( struct attended_transfer_properties props,
enum attended_transfer_stimulus  stimulus 
)
static

Definition at line 2128 of file bridge_basic.c.

2130{
2131 switch (stimulus) {
2133 play_failsound(props->transferer);
2134 publish_transfer_fail(props);
2135 return TRANSFER_FAIL;
2141 return TRANSFER_CONSULTING;
2143 case STIMULUS_TIMEOUT:
2145 play_failsound(props->transferer);
2146 return TRANSFER_REBRIDGE;
2149 return TRANSFER_THREEWAY;
2151 return TRANSFER_HESITANT;
2152 case STIMULUS_NONE:
2155 default:
2156 ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2157 stimulus_strs[stimulus], state_properties[props->state].state_name);
2158 return props->state;
2159 }
2160}
static void play_failsound(struct ast_channel *chan)
Helper method to play a fail sound on a channel in a bridge.
static void publish_transfer_fail(struct attended_transfer_properties *props)
Send a stasis publication for a failed attended transfer.
static void bridge_unhold(struct ast_bridge *bridge)
Helper method to send an unhold frame to all channels in a bridge.

References ast_log, attended_transfer_properties::atxferdropcall, bridge_unhold(), LOG_WARNING, play_failsound(), publish_transfer_fail(), attended_transfer_properties::state, attended_transfer_state_properties::state_name, state_properties, STIMULUS_DTMF_ATXFER_ABORT, STIMULUS_DTMF_ATXFER_COMPLETE, STIMULUS_DTMF_ATXFER_SWAP, STIMULUS_DTMF_ATXFER_THREEWAY, STIMULUS_NONE, STIMULUS_RECALL_TARGET_ANSWER, STIMULUS_RECALL_TARGET_HANGUP, stimulus_strs, STIMULUS_TIMEOUT, STIMULUS_TRANSFER_TARGET_ANSWER, STIMULUS_TRANSFER_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, STIMULUS_TRANSFERER_HANGUP, TRANSFER_BLOND, TRANSFER_BLOND_NONFINAL, TRANSFER_CONSULTING, TRANSFER_FAIL, TRANSFER_HESITANT, TRANSFER_REBRIDGE, TRANSFER_THREEWAY, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer.

◆ clear_stimulus_queue()

static void clear_stimulus_queue ( struct attended_transfer_properties props)
static

Free backlog of stimuli in the queue.

Definition at line 1508 of file bridge_basic.c.

1509{
1510 struct stimulus_list *list;
1511 SCOPED_AO2LOCK(lock, props);
1512
1513 while ((list = AST_LIST_REMOVE_HEAD(&props->stimulus_queue, next))) {
1514 ast_free(list);
1515 }
1516}
#define ast_free(a)
Definition: astmm.h:180
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
struct attended_transfer_properties::@313 stimulus_queue
struct stimulus_list * next

References ast_free, AST_LIST_REMOVE_HEAD, lock, stimulus_list::next, SCOPED_AO2LOCK, and attended_transfer_properties::stimulus_queue.

Referenced by attended_transfer_properties_shutdown().

◆ common_recall_channel_setup()

static void common_recall_channel_setup ( struct ast_channel recall,
struct ast_channel transferer 
)
static

Definition at line 2453 of file bridge_basic.c.

2454{
2455 ast_callid callid;
2456
2458 if (callid) {
2459 ast_channel_callid_set(recall, callid);
2460 }
2461
2462 ast_channel_inherit_variables(transferer, recall);
2463 ast_channel_datastore_inherit(transferer, recall);
2464
2465 /*
2466 * Stage a snapshot to ensure that a snapshot is always done
2467 * on the recall channel so earlier COLP and CLID setup will
2468 * get published.
2469 */
2473}
@ AST_CHANNEL_REQUESTOR_REPLACEMENT
Definition: channel.h:1525
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2387
void ast_channel_req_accountcodes(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship)
Setup new channel accountcodes from the requestor channel after ast_request().
Definition: channel.c:6453
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
Definition: channel.c:6790
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:2298

References ast_channel_callid_set(), ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_req_accountcodes(), AST_CHANNEL_REQUESTOR_REPLACEMENT, ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_read_threadstorage_callid(), and attended_transfer_properties::transferer.

Referenced by recalling_enter(), and retransfer_enter().

◆ complete_enter()

static int complete_enter ( struct attended_transfer_properties props)
static

Definition at line 2328 of file bridge_basic.c.

2329{
2330 struct ast_channel *transferee_channel;
2331 struct ast_channel *target_channel;
2332
2334 &transferee_channel, &target_channel);
2335 bridge_merge(props->transferee_bridge, props->target_bridge, &props->transferer, 1);
2336 play_sound(props->transfer_target, props->xfersound);
2337 publish_transfer_success(props, transferee_channel, target_channel);
2338
2339 ast_channel_cleanup(transferee_channel);
2340 ast_channel_cleanup(target_channel);
2341 return 0;
2342}
static void play_sound(struct ast_channel *chan, const char *sound)
Helper method to play a sound on a channel in a bridge.
const ast_string_field xfersound

References ast_channel_cleanup, bridge_merge(), get_transfer_parties(), play_sound(), publish_transfer_success(), attended_transfer_properties::target_bridge, attended_transfer_properties::transfer_target, attended_transfer_properties::transferee_bridge, attended_transfer_properties::transferer, and attended_transfer_properties::xfersound.

◆ consulting_enter()

static int consulting_enter ( struct attended_transfer_properties props)
static

Definition at line 2231 of file bridge_basic.c.

2232{
2233 return 0;
2234}

◆ consulting_exit()

static enum attended_transfer_state consulting_exit ( struct attended_transfer_properties props,
enum attended_transfer_stimulus  stimulus 
)
static

Definition at line 2236 of file bridge_basic.c.

2238{
2239 switch (stimulus) {
2241 /* This is a one-of-a-kind event. The transferer and transfer target are talking in
2242 * one bridge, and the transferee has hung up in a separate bridge. In this case, we
2243 * will change the personality of the transfer target bridge back to normal, and play
2244 * a sound to the transferer to indicate the transferee is gone.
2245 */
2247 play_failsound(props->transferer);
2249 /* These next two lines are here to ensure that our reference to the target bridge
2250 * is cleaned up properly and that the target bridge is not destroyed when the
2251 * monitor thread exits
2252 */
2253 ao2_ref(props->target_bridge, -1);
2254 props->target_bridge = NULL;
2255 return TRANSFER_FAIL;
2258 /* We know the transferer is in the target_bridge, so take the other bridge off hold */
2260 return TRANSFER_COMPLETE;
2262 return TRANSFER_REBRIDGE;
2264 play_failsound(props->transferer);
2265 return TRANSFER_REBRIDGE;
2268 return TRANSFER_THREEWAY;
2270 hold(props->transferer);
2272 unhold(props->transferer);
2274 case STIMULUS_NONE:
2275 case STIMULUS_TIMEOUT:
2279 default:
2280 ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2281 stimulus_strs[stimulus], state_properties[props->state].state_name);
2282 return props->state;
2283 }
2284}

References ao2_ref, ast_bridge_merge_inhibit(), ast_log, bridge_basic_change_personality(), BRIDGE_BASIC_PERSONALITY_NORMAL, bridge_move(), bridge_unhold(), hold(), LOG_WARNING, NULL, play_failsound(), attended_transfer_properties::state, attended_transfer_state_properties::state_name, state_properties, STIMULUS_DTMF_ATXFER_ABORT, STIMULUS_DTMF_ATXFER_COMPLETE, STIMULUS_DTMF_ATXFER_SWAP, STIMULUS_DTMF_ATXFER_THREEWAY, STIMULUS_NONE, STIMULUS_RECALL_TARGET_ANSWER, STIMULUS_RECALL_TARGET_HANGUP, stimulus_strs, STIMULUS_TIMEOUT, STIMULUS_TRANSFER_TARGET_ANSWER, STIMULUS_TRANSFER_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, STIMULUS_TRANSFERER_HANGUP, attended_transfer_properties::target_bridge, TRANSFER_COMPLETE, TRANSFER_DOUBLECHECKING, TRANSFER_FAIL, TRANSFER_REBRIDGE, TRANSFER_THREEWAY, attended_transfer_properties::transferee_bridge, attended_transfer_properties::transferer, and unhold().

◆ copy_caller_data()

static void copy_caller_data ( struct ast_channel dest,
struct ast_channel caller 
)
static

Definition at line 3282 of file bridge_basic.c.

3283{
3284 ast_channel_lock_both(caller, dest);
3286 ast_channel_inherit_variables(caller, dest);
3287 ast_channel_datastore_inherit(caller, dest);
3288 ast_channel_unlock(dest);
3289 ast_channel_unlock(caller);
3290}
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2975
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:8315
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)

References ast_channel_caller(), ast_channel_connected(), ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_lock_both, ast_channel_unlock, and ast_connected_line_copy_from_caller().

Referenced by blind_transfer_cb(), and dial_transfer().

◆ dial_transfer()

static struct ast_channel * dial_transfer ( struct ast_channel caller,
const char *  destination 
)
static

Helper function that creates an outgoing channel and returns it immediately.

Definition at line 3293 of file bridge_basic.c.

3294{
3295 struct ast_channel *chan;
3296 int cause;
3297 struct ast_format_cap *caps;
3298
3299 ast_channel_lock(caller);
3300 caps = ao2_bump(ast_channel_nativeformats(caller));
3301 ast_channel_unlock(caller);
3302
3303 /* Now we request a local channel to prepare to call the destination */
3304 chan = ast_request("Local", caps, NULL, caller, destination, &cause);
3305
3306 ao2_cleanup(caps);
3307
3308 if (!chan) {
3309 return NULL;
3310 }
3311
3312 ast_channel_lock_both(chan, caller);
3313
3315
3316 /* Who is transferring the call. */
3317 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", ast_channel_name(caller));
3318
3320
3321 ast_channel_unlock(chan);
3322 ast_channel_unlock(caller);
3323
3324 /* Before we actually dial out let's inherit appropriate information. */
3325 copy_caller_data(chan, caller);
3326
3327 return chan;
3328}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void ast_bridge_set_transfer_variables(struct ast_channel *chan, const char *value, int is_attended)
Set the relevant transfer variables for a single channel.
Definition: bridge.c:4352
@ AST_CHANNEL_REQUESTOR_BRIDGE_PEER
Definition: channel.h:1523
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct ast_channel * ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
Requests a channel.
Definition: channel.c:6373
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.
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54

References ao2_bump, ao2_cleanup, ast_bridge_set_transfer_variables(), ast_channel_lock, ast_channel_lock_both, ast_channel_name(), ast_channel_nativeformats(), ast_channel_req_accountcodes(), AST_CHANNEL_REQUESTOR_BRIDGE_PEER, ast_channel_unlock, ast_request(), copy_caller_data(), NULL, and pbx_builtin_setvar_helper().

Referenced by feature_attended_transfer().

◆ double_checking_enter()

static int double_checking_enter ( struct attended_transfer_properties props)
static

Definition at line 2286 of file bridge_basic.c.

2287{
2288 return 0;
2289}

◆ double_checking_exit()

static enum attended_transfer_state double_checking_exit ( struct attended_transfer_properties props,
enum attended_transfer_stimulus  stimulus 
)
static

Definition at line 2291 of file bridge_basic.c.

2293{
2294 switch (stimulus) {
2296 play_failsound(props->transferer);
2297 publish_transfer_fail(props);
2298 return TRANSFER_FAIL;
2301 /* We know the transferer is in the transferee, so take the other bridge off hold */
2303 return TRANSFER_COMPLETE;
2306 play_failsound(props->transferer);
2307 return TRANSFER_RESUME;
2310 return TRANSFER_THREEWAY;
2312 hold(props->transferer);
2314 unhold(props->transferer);
2315 return TRANSFER_CONSULTING;
2316 case STIMULUS_NONE:
2317 case STIMULUS_TIMEOUT:
2321 default:
2322 ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2323 stimulus_strs[stimulus], state_properties[props->state].state_name);
2324 return props->state;
2325 }
2326}

References ast_log, bridge_move(), bridge_unhold(), hold(), LOG_WARNING, NULL, play_failsound(), publish_transfer_fail(), attended_transfer_properties::state, attended_transfer_state_properties::state_name, state_properties, STIMULUS_DTMF_ATXFER_ABORT, STIMULUS_DTMF_ATXFER_COMPLETE, STIMULUS_DTMF_ATXFER_SWAP, STIMULUS_DTMF_ATXFER_THREEWAY, STIMULUS_NONE, STIMULUS_RECALL_TARGET_ANSWER, STIMULUS_RECALL_TARGET_HANGUP, stimulus_strs, STIMULUS_TIMEOUT, STIMULUS_TRANSFER_TARGET_ANSWER, STIMULUS_TRANSFER_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, STIMULUS_TRANSFERER_HANGUP, attended_transfer_properties::target_bridge, TRANSFER_COMPLETE, TRANSFER_CONSULTING, TRANSFER_FAIL, TRANSFER_RESUME, TRANSFER_THREEWAY, attended_transfer_properties::transferee_bridge, attended_transfer_properties::transferer, and unhold().

◆ dtmf_features_flags_to_string()

static int dtmf_features_flags_to_string ( struct ast_flags feature_flags,
char *  buffer,
size_t  buffer_size 
)
static

Definition at line 133 of file bridge_basic.c.

134{
135 size_t buffer_expended = 0;
136 unsigned int cur_feature;
137 static const struct {
138 char letter;
139 unsigned int flag;
140 } associations[] = {
141 { 'T', AST_FEATURE_REDIRECT },
142 { 'K', AST_FEATURE_PARKCALL },
143 { 'H', AST_FEATURE_DISCONNECT },
144 { 'W', AST_FEATURE_AUTOMON },
145 { 'X', AST_FEATURE_AUTOMIXMON },
146 };
147
148 for (cur_feature = 0; cur_feature < ARRAY_LEN(associations); cur_feature++) {
149 if (ast_test_flag(feature_flags, associations[cur_feature].flag)) {
150 if (buffer_expended == buffer_size - 1) {
151 buffer[buffer_expended] = '\0';
152 return -1;
153 }
154 buffer[buffer_expended++] = associations[cur_feature].letter;
155 }
156 }
157
158 buffer[buffer_expended] = '\0';
159 return 0;
160}
@ AST_FEATURE_AUTOMIXMON
Definition: channel.h:1089
@ AST_FEATURE_REDIRECT
Definition: channel.h:1084
@ AST_FEATURE_PARKCALL
Definition: channel.h:1088
@ AST_FEATURE_AUTOMON
Definition: channel.h:1087
@ AST_FEATURE_DISCONNECT
Definition: channel.h:1085
long int flag
Definition: f2c.h:83
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, AST_FEATURE_AUTOMIXMON, AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, and ast_test_flag.

Referenced by ast_bridge_features_ds_get_string().

◆ dynamic_dtmf_hook_add()

static int dynamic_dtmf_hook_add ( struct ast_bridge_features features,
unsigned int  flags,
const char *  dtmf,
const char *  feature_name,
const char *  app_name,
const char *  app_args,
const char *  moh_class 
)
static

Definition at line 543 of file bridge_basic.c.

544{
545 struct dynamic_dtmf_hook_data *hook_data;
546 size_t len_name = strlen(app_name) + 1;
547 size_t len_args = ast_strlen_zero(app_args) ? 0 : strlen(app_args) + 1;
548 size_t len_moh = ast_strlen_zero(moh_class) ? 0 : strlen(moh_class) + 1;
549 size_t len_feature = strlen(feature_name) + 1;
550 size_t len_data = sizeof(*hook_data) + len_name + len_args + len_moh + len_feature;
551 int res;
552
553 /* Fill in application run hook data. */
554 hook_data = ast_malloc(len_data);
555 if (!hook_data) {
556 return -1;
557 }
558 hook_data->flags = flags;
559 hook_data->app_args_offset = len_args ? len_name : 0;
560 hook_data->moh_offset = len_moh ? len_name + len_args : 0;
561 hook_data->feature_offset = len_name + len_args + len_moh;
562 strcpy(hook_data->app_name, app_name);/* Safe */
563 if (len_args) {
564 strcpy(&hook_data->app_name[hook_data->app_args_offset], app_args);/* Safe */
565 }
566 if (len_moh) {
567 strcpy(&hook_data->app_name[hook_data->moh_offset], moh_class);/* Safe */
568 }
569 strcpy(&hook_data->app_name[hook_data->feature_offset], feature_name);/* Safe */
570
571 res = ast_bridge_dtmf_hook(features, dtmf, dynamic_dtmf_hook_trip, hook_data,
574 if (res) {
575 ast_free(hook_data);
576 }
577 return res;
578}
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
static int dynamic_dtmf_hook_trip(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Definition: bridge_basic.c:475
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463

References dynamic_dtmf_hook_data::app_args_offset, app_name(), dynamic_dtmf_hook_data::app_name, ast_bridge_dtmf_hook(), AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE, AST_BRIDGE_HOOK_REMOVE_ON_PULL, ast_free, ast_free_ptr(), ast_malloc, ast_strlen_zero(), dynamic_dtmf_hook_trip(), dynamic_dtmf_hook_data::feature_offset, dynamic_dtmf_hook_data::flags, and dynamic_dtmf_hook_data::moh_offset.

Referenced by setup_dynamic_feature().

◆ dynamic_dtmf_hook_callback()

static void dynamic_dtmf_hook_callback ( struct ast_bridge_channel bridge_channel,
const void *  payload,
size_t  payload_size 
)
static

Definition at line 435 of file bridge_basic.c.

437{
438 struct ast_channel *chan = bridge_channel->chan;
439 const struct dynamic_dtmf_hook_run *run_data = payload;
440
441 pbx_builtin_setvar_helper(chan, "DYNAMIC_FEATURENAME",
442 &run_data->app_name[run_data->feature_offset]);
443 pbx_builtin_setvar_helper(chan, "DYNAMIC_WHO_ACTIVATED",
444 &run_data->app_name[run_data->activated_offset]);
445
446 ast_bridge_channel_run_app(bridge_channel, run_data->app_name,
447 run_data->app_args_offset ? &run_data->app_name[run_data->app_args_offset] : NULL,
448 run_data->moh_offset ? &run_data->app_name[run_data->moh_offset] : NULL);
449}
void ast_bridge_channel_run_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
Run an application on the bridge channel.
struct ast_bridge_channel * bridge_channel

References dynamic_dtmf_hook_run::activated_offset, dynamic_dtmf_hook_run::app_args_offset, dynamic_dtmf_hook_run::app_name, ast_bridge_channel_run_app(), ast_channel::bridge_channel, ast_bridge_channel::chan, dynamic_dtmf_hook_run::feature_offset, dynamic_dtmf_hook_run::moh_offset, NULL, and pbx_builtin_setvar_helper().

Referenced by dynamic_dtmf_hook_trip().

◆ dynamic_dtmf_hook_trip()

static int dynamic_dtmf_hook_trip ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

Definition at line 475 of file bridge_basic.c.

476{
477 struct dynamic_dtmf_hook_data *pvt = hook_pvt;
478 struct dynamic_dtmf_hook_run *run_data;
479 const char *activated_name;
480 size_t len_name;
481 size_t len_args;
482 size_t len_moh;
483 size_t len_feature;
484 size_t len_activated;
485 size_t len_data;
486
487 /* Determine lengths of things. */
488 len_name = strlen(pvt->app_name) + 1;
489 len_args = pvt->app_args_offset ? strlen(&pvt->app_name[pvt->app_args_offset]) + 1 : 0;
490 len_moh = pvt->moh_offset ? strlen(&pvt->app_name[pvt->moh_offset]) + 1 : 0;
491 len_feature = strlen(&pvt->app_name[pvt->feature_offset]) + 1;
492 ast_channel_lock(bridge_channel->chan);
493 activated_name = ast_strdupa(ast_channel_name(bridge_channel->chan));
494 ast_channel_unlock(bridge_channel->chan);
495 len_activated = strlen(activated_name) + 1;
496 len_data = sizeof(*run_data) + len_name + len_args + len_moh + len_feature + len_activated;
497
498 /* Fill in dynamic feature run hook data. */
499 run_data = ast_alloca(len_data);
500 run_data->app_args_offset = len_args ? len_name : 0;
501 run_data->moh_offset = len_moh ? len_name + len_args : 0;
502 run_data->feature_offset = len_name + len_args + len_moh;
503 run_data->activated_offset = len_name + len_args + len_moh + len_feature;
504 strcpy(run_data->app_name, pvt->app_name);/* Safe */
505 if (len_args) {
506 strcpy(&run_data->app_name[run_data->app_args_offset],
507 &pvt->app_name[pvt->app_args_offset]);/* Safe */
508 }
509 if (len_moh) {
510 strcpy(&run_data->app_name[run_data->moh_offset],
511 &pvt->app_name[pvt->moh_offset]);/* Safe */
512 }
513 strcpy(&run_data->app_name[run_data->feature_offset],
514 &pvt->app_name[pvt->feature_offset]);/* Safe */
515 strcpy(&run_data->app_name[run_data->activated_offset], activated_name);/* Safe */
516
520 dynamic_dtmf_hook_callback, run_data, len_data);
521 } else {
522 dynamic_dtmf_hook_callback(bridge_channel, run_data, len_data);
523 }
524 return 0;
525}
static void dynamic_dtmf_hook_callback(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
Definition: bridge_basic.c:435
@ AST_BRIDGE_CHANNEL_CB_OPTION_MEDIA
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.
@ AST_FEATURE_FLAG_ONPEER
Definition: features.h:35

References dynamic_dtmf_hook_run::activated_offset, dynamic_dtmf_hook_run::app_args_offset, dynamic_dtmf_hook_data::app_args_offset, dynamic_dtmf_hook_run::app_name, dynamic_dtmf_hook_data::app_name, ast_alloca, AST_BRIDGE_CHANNEL_CB_OPTION_MEDIA, ast_bridge_channel_write_callback(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, AST_FEATURE_FLAG_ONPEER, ast_strdupa, ast_test_flag, ast_bridge_channel::chan, dynamic_dtmf_hook_callback(), dynamic_dtmf_hook_run::feature_offset, dynamic_dtmf_hook_data::feature_offset, dynamic_dtmf_hook_run::moh_offset, and dynamic_dtmf_hook_data::moh_offset.

Referenced by dynamic_dtmf_hook_add().

◆ fail_enter()

static int fail_enter ( struct attended_transfer_properties props)
static

Definition at line 2747 of file bridge_basic.c.

2748{
2749 if (props->transferee_bridge) {
2751 props->transferee_bridge = NULL;
2752 }
2753 return 0;
2754}

References ast_bridge_destroy(), NULL, and attended_transfer_properties::transferee_bridge.

◆ feature_attended_transfer()

static int feature_attended_transfer ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

Internal built in feature for attended transfers.

This hook will set up a thread for monitoring the progress of an attended transfer. For more information about attended transfer progress, see documentation on the transfer state machine.

Parameters
bridge_channelThe channel that pressed the attended transfer DTMF sequence
hook_pvtStructure with further information about the attended transfer

Definition at line 3340 of file bridge_basic.c.

3341{
3342 struct ast_bridge_features_attended_transfer *attended_transfer = hook_pvt;
3343 struct attended_transfer_properties *props;
3344 struct ast_bridge *bridge;
3345 char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
3346 char exten[AST_MAX_EXTENSION] = "";
3347 pthread_t thread;
3348
3349 /* Inhibit the bridge before we do anything else. */
3350 bridge = ast_bridge_channel_merge_inhibit(bridge_channel, +1);
3351
3352 ast_verb(3, "Channel %s: Started DTMF attended transfer.\n",
3353 ast_channel_name(bridge_channel->chan));
3354
3355 if (strcmp(bridge->v_table->name, "basic")) {
3356 ast_log(LOG_ERROR, "Channel %s: Attended transfer attempted on unsupported bridge type '%s'.\n",
3357 ast_channel_name(bridge_channel->chan), bridge->v_table->name);
3358 ast_bridge_merge_inhibit(bridge, -1);
3359 ao2_ref(bridge, -1);
3360 return 0;
3361 }
3362
3363 /* Was the bridge inhibited before we inhibited it? */
3364 if (1 < bridge->inhibit_merge) {
3365 /*
3366 * The peer likely initiated attended transfer at the same time
3367 * and we lost the race.
3368 */
3369 ast_verb(3, "Channel %s: Bridge '%s' does not permit merging at this time.\n",
3370 ast_channel_name(bridge_channel->chan), bridge->uniqueid);
3371 ast_bridge_merge_inhibit(bridge, -1);
3372 ao2_ref(bridge, -1);
3373 return 0;
3374 }
3375
3376 props = attended_transfer_properties_alloc(bridge_channel->chan,
3377 attended_transfer ? attended_transfer->context : NULL);
3378 if (!props) {
3379 ast_log(LOG_ERROR, "Channel %s: Unable to allocate control structure for performing attended transfer.\n",
3380 ast_channel_name(bridge_channel->chan));
3381 ast_bridge_merge_inhibit(bridge, -1);
3382 ao2_ref(bridge, -1);
3383 return 0;
3384 }
3385
3386 props->transferee_bridge = bridge;
3387
3388 if (add_transferer_role(props->transferer, attended_transfer)) {
3389 ast_log(LOG_ERROR, "Channel %s: Unable to set transferrer bridge role.\n",
3390 ast_channel_name(bridge_channel->chan));
3392 return 0;
3393 }
3394
3395 ast_bridge_channel_write_hold(bridge_channel, NULL);
3396
3397 /* Grab the extension to transfer to */
3398 if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), props->context)) {
3399 /*
3400 * This is a normal exit for when the user fails
3401 * to specify a valid transfer target. e.g., The user
3402 * hungup, didn't dial any digits, or dialed an invalid
3403 * extension.
3404 */
3405 ast_verb(3, "Channel %s: Unable to acquire target extension for attended transfer.\n",
3406 ast_channel_name(bridge_channel->chan));
3407 ast_bridge_channel_write_unhold(bridge_channel);
3409 return 0;
3410 }
3411
3412 ast_string_field_set(props, exten, exten);
3413
3414 /* Fill the variable with the extension and context we want to call */
3415 snprintf(destination, sizeof(destination), "%s@%s", props->exten, props->context);
3416
3417 ast_debug(1, "Channel %s: Attended transfer target '%s'\n",
3418 ast_channel_name(bridge_channel->chan), destination);
3419
3420 /* Get a channel that is the destination we wish to call */
3421 props->transfer_target = dial_transfer(bridge_channel->chan, destination);
3422 if (!props->transfer_target) {
3423 ast_log(LOG_ERROR, "Channel %s: Unable to request outbound channel for attended transfer target.\n",
3424 ast_channel_name(bridge_channel->chan));
3426 ast_bridge_channel_write_unhold(bridge_channel);
3428 return 0;
3429 }
3430
3431
3432 /* Create a bridge to use to talk to the person we are calling */
3434 if (!props->target_bridge) {
3435 ast_log(LOG_ERROR, "Channel %s: Unable to create bridge for attended transfer target.\n",
3436 ast_channel_name(bridge_channel->chan));
3438 ast_bridge_channel_write_unhold(bridge_channel);
3440 props->transfer_target = NULL;
3442 return 0;
3443 }
3445
3446 if (attach_framehook(props, props->transfer_target)) {
3447 ast_log(LOG_ERROR, "Channel %s: Unable to attach framehook to transfer target.\n",
3448 ast_channel_name(bridge_channel->chan));
3450 ast_bridge_channel_write_unhold(bridge_channel);
3452 props->transfer_target = NULL;
3454 return 0;
3455 }
3456
3461
3462 if (ast_call(props->transfer_target, destination, 0)) {
3463 ast_log(LOG_ERROR, "Channel %s: Unable to place outbound call to transfer target.\n",
3464 ast_channel_name(bridge_channel->chan));
3466 ast_bridge_channel_write_unhold(bridge_channel);
3468 props->transfer_target = NULL;
3470 return 0;
3471 }
3472
3473 /* We increase the refcount of the transfer target because ast_bridge_impart() will
3474 * steal the reference we already have. We need to keep a reference, so the only
3475 * choice is to give it a bump
3476 */
3480 ast_log(LOG_ERROR, "Channel %s: Unable to place transfer target into bridge.\n",
3481 ast_channel_name(bridge_channel->chan));
3483 ast_bridge_channel_write_unhold(bridge_channel);
3485 props->transfer_target = NULL;
3487 return 0;
3488 }
3489
3491 ast_log(LOG_ERROR, "Channel %s: Unable to create monitoring thread for attended transfer.\n",
3492 ast_channel_name(bridge_channel->chan));
3494 ast_bridge_channel_write_unhold(bridge_channel);
3496 return 0;
3497 }
3498
3499 /* Once the monitoring thread has been created, it is responsible for destroying all
3500 * of the necessary components.
3501 */
3502 return 0;
3503}
pthread_t thread
Definition: app_sla.c:329
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
Definition: bridge.c:1878
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition: bridge.h:590
static struct attended_transfer_properties * attended_transfer_properties_alloc(struct ast_channel *transferer, const char *context)
Allocate and initialize attended transfer properties.
static void stream_failsound(struct ast_channel *chan)
Helper method to stream a fail sound on a channel.
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
static struct ast_channel * dial_transfer(struct ast_channel *caller, const char *destination)
Helper function that creates an outgoing channel and returns it immediately.
static int add_transferer_role(struct ast_channel *chan, struct ast_bridge_features_attended_transfer *attended_transfer)
static void * attended_transfer_monitor_thread(void *data)
The main loop for the attended transfer monitor thread.
static int grab_transfer(struct ast_channel *chan, char *exten, size_t exten_len, const char *context)
Helper function that presents dialtone and grabs extension.
static int attach_framehook(struct attended_transfer_properties *props, struct ast_channel *channel)
int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel)
Write an unhold frame into the bridge.
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.
int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, const char *moh_class)
Write a hold frame into the bridge.
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
Definition: channel.c:6480
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2560
#define AST_MAX_CONTEXT
Definition: channel.h:135
#define AST_MAX_EXTENSION
Definition: channel.h:134
#define ast_verb(level,...)
Structure that contains configuration information for the attended transfer built in feature.
const struct ast_bridge_methods * v_table
Definition: bridge.h:351
const ast_string_field uniqueid
Definition: bridge.h:401
unsigned int inhibit_merge
Count of the active temporary requests to inhibit bridge merges. Zero if merges are allowed.
Definition: bridge.h:384
const ast_string_field context
const ast_string_field exten
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:588

References add_transferer_role(), ao2_ref, ast_bridge_basic_new(), ast_bridge_channel_merge_inhibit(), ast_bridge_channel_write_hold(), ast_bridge_channel_write_unhold(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_bridge_merge_inhibit(), ast_call(), ast_channel_name(), ast_channel_ref, ast_debug, ast_hangup(), ast_log, AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_pthread_create_detached, ast_string_field_set, ast_verb, attach_framehook(), attended_transfer_monitor_thread(), attended_transfer_properties_alloc(), attended_transfer_properties_shutdown(), bridge_basic_change_personality(), BRIDGE_BASIC_PERSONALITY_ATXFER, ast_bridge_channel::chan, ast_bridge_features_attended_transfer::context, attended_transfer_properties::context, dial_transfer(), attended_transfer_properties::exten, grab_transfer(), ast_bridge::inhibit_merge, LOG_ERROR, ast_bridge_methods::name, NULL, stream_failsound(), attended_transfer_properties::target_bridge, thread, attended_transfer_properties::transfer_target, attended_transfer_properties::transferee_bridge, attended_transfer_properties::transferer, ast_bridge::uniqueid, and ast_bridge::v_table.

Referenced by ast_bridging_init_basic().

◆ feature_blind_transfer()

static int feature_blind_transfer ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

Internal built in feature for blind transfers.

Definition at line 3516 of file bridge_basic.c.

3517{
3518 char xfer_exten[AST_MAX_EXTENSION] = "";
3519 struct ast_bridge_features_blind_transfer *blind_transfer = hook_pvt;
3520 const char *xfer_context;
3521 char *goto_on_blindxfer;
3522
3523 ast_verb(3, "Channel %s: Started DTMF blind transfer.\n",
3524 ast_channel_name(bridge_channel->chan));
3525
3526 ast_bridge_channel_write_hold(bridge_channel, NULL);
3527
3528 ast_channel_lock(bridge_channel->chan);
3529 xfer_context = ast_strdupa(get_transfer_context(bridge_channel->chan,
3530 blind_transfer ? blind_transfer->context : NULL));
3531 goto_on_blindxfer = ast_strdupa(S_OR(pbx_builtin_getvar_helper(bridge_channel->chan,
3532 "GOTO_ON_BLINDXFR"), ""));
3533 ast_channel_unlock(bridge_channel->chan);
3534
3535 /* Grab the extension to transfer to */
3536 if (grab_transfer(bridge_channel->chan, xfer_exten, sizeof(xfer_exten), xfer_context)) {
3537 ast_bridge_channel_write_unhold(bridge_channel);
3538 return 0;
3539 }
3540
3541 ast_debug(1, "Channel %s: Blind transfer target '%s@%s'\n",
3542 ast_channel_name(bridge_channel->chan), xfer_exten, xfer_context);
3543
3544 if (!ast_strlen_zero(goto_on_blindxfer)) {
3545 const char *chan_context;
3546 const char *chan_exten;
3547 int chan_priority;
3548
3549 ast_debug(1, "Channel %s: After transfer, transferrer goes to %s\n",
3550 ast_channel_name(bridge_channel->chan), goto_on_blindxfer);
3551
3552 ast_channel_lock(bridge_channel->chan);
3553 chan_context = ast_strdupa(ast_channel_context(bridge_channel->chan));
3554 chan_exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
3555 chan_priority = ast_channel_priority(bridge_channel->chan);
3556 ast_channel_unlock(bridge_channel->chan);
3557 ast_bridge_set_after_go_on(bridge_channel->chan,
3558 chan_context, chan_exten, chan_priority, goto_on_blindxfer);
3559 }
3560
3561 if (ast_bridge_transfer_blind(0, bridge_channel->chan, xfer_exten, xfer_context,
3563 && !ast_strlen_zero(goto_on_blindxfer)) {
3564 ast_bridge_discard_after_goto(bridge_channel->chan);
3565 }
3566
3567 return 0;
3568}
enum ast_transfer_result ast_bridge_transfer_blind(int is_external, struct ast_channel *transferer, const char *exten, const char *context, transfer_channel_cb new_channel_cb, void *user_data)
Blind transfer target to the extension and context provided.
Definition: bridge.c:4425
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition: bridge.h:1100
void ast_bridge_discard_after_goto(struct ast_channel *chan)
Discard channel after bridge goto location.
Definition: bridge_after.c:384
void ast_bridge_set_after_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto)
Set channel to go on in the dialplan after the bridge.
Definition: bridge_after.c:622
static void blind_transfer_cb(struct ast_channel *new_channel, struct transfer_channel_data *user_data_wrapper, enum ast_transfer_type transfer_type)
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
const char * ast_channel_exten(const struct ast_channel *chan)
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Structure that contains configuration information for the blind transfer built in feature.

References ast_bridge_channel_write_hold(), ast_bridge_channel_write_unhold(), ast_bridge_discard_after_goto(), ast_bridge_set_after_go_on(), ast_bridge_transfer_blind(), AST_BRIDGE_TRANSFER_SUCCESS, ast_channel_context(), ast_channel_exten(), ast_channel_lock, ast_channel_name(), ast_channel_priority(), ast_channel_unlock, ast_debug, AST_MAX_EXTENSION, ast_strdupa, ast_strlen_zero(), ast_verb, blind_transfer_cb(), ast_bridge_channel::chan, ast_bridge_features_blind_transfer::context, get_transfer_context(), grab_transfer(), NULL, pbx_builtin_getvar_helper(), and S_OR.

Referenced by ast_bridging_init_basic().

◆ get_transfer_context()

static const char * get_transfer_context ( struct ast_channel transferer,
const char *  context 
)
static

Definition at line 1379 of file bridge_basic.c.

1380{
1381 if (!ast_strlen_zero(context)) {
1382 return context;
1383 }
1384 context = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
1385 if (!ast_strlen_zero(context)) {
1386 return context;
1387 }
1388 context = ast_channel_context(transferer);
1389 if (!ast_strlen_zero(context)) {
1390 return context;
1391 }
1392 return "default";
1393}

References ast_channel_context(), ast_strlen_zero(), voicemailpwcheck::context, pbx_builtin_getvar_helper(), and attended_transfer_properties::transferer.

Referenced by attended_transfer_properties_alloc(), and feature_blind_transfer().

◆ get_transfer_exten()

static const char * get_transfer_exten ( struct ast_channel transferer,
const char *  exten 
)
static

Definition at line 1404 of file bridge_basic.c.

1405{
1406 if (!ast_strlen_zero(exten)) {
1407 return exten;
1408 }
1409 exten = pbx_builtin_getvar_helper(transferer, "TRANSFER_EXTEN");
1410 if (!ast_strlen_zero(exten)) {
1411 return exten;
1412 }
1413 return ""; /* empty default, to get transfer extension from user now */
1414}

References ast_strlen_zero(), attended_transfer_properties::exten, pbx_builtin_getvar_helper(), and attended_transfer_properties::transferer.

Referenced by grab_transfer().

◆ get_transfer_parties()

static void get_transfer_parties ( struct ast_channel transferer,
struct ast_bridge transferee_bridge,
struct ast_bridge target_bridge,
struct ast_channel **  transferee,
struct ast_channel **  transfer_target 
)
static

determine transferee and transfer target for an attended transfer

In builtin attended transfers, there is a single transferer channel that jumps between the two bridges involved. At the time the attended transfer occurs, the transferer could be in either bridge, so determining the parties is a bit more complex than normal.

The method used here is to determine which of the two bridges the transferer is in, and grabbing the peer from that bridge. The other bridge, if it only has a single channel in it, has the other desired channel.

Parameters
transfererThe channel performing the transfer
transferee_bridgeThe bridge that the transferee is in
target_bridgeThe bridge that the transfer target is in
[out]transfereeThe transferee channel
[out]transfer_targetThe transfer target channel

Definition at line 1634 of file bridge_basic.c.

1637{
1638 struct ast_bridge *transferer_bridge;
1639
1640 ast_channel_lock(transferer);
1641 transferer_bridge = ast_channel_get_bridge(transferer);
1642 ast_channel_unlock(transferer);
1643
1644 if (transferer_bridge == transferee_bridge) {
1645 get_transfer_parties_transferer_bridge(transferee_bridge, target_bridge,
1646 transferer, transferee, transfer_target);
1647 } else if (transferer_bridge == target_bridge) {
1648 get_transfer_parties_transferer_bridge(target_bridge, transferee_bridge,
1649 transferer, transfer_target, transferee);
1650 } else {
1651 get_transfer_party_non_transferer_bridge(transferee_bridge, transferee);
1652 get_transfer_party_non_transferer_bridge(target_bridge, transfer_target);
1653 }
1654
1655 ao2_cleanup(transferer_bridge);
1656}
static void get_transfer_parties_transferer_bridge(struct ast_bridge *transferer_bridge, struct ast_bridge *other_bridge, struct ast_channel *transferer, struct ast_channel **transferer_peer, struct ast_channel **other_party)
Get the transferee and transfer target when the transferer is in a bridge with one of the desired par...
static void get_transfer_party_non_transferer_bridge(struct ast_bridge *bridge, struct ast_channel **party)
Get a desired transfer party for a bridge the transferer is not in.
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition: channel.c:10556

References ao2_cleanup, ast_channel_get_bridge(), ast_channel_lock, ast_channel_unlock, get_transfer_parties_transferer_bridge(), and get_transfer_party_non_transferer_bridge().

Referenced by blond_enter(), complete_enter(), and threeway_enter().

◆ get_transfer_parties_transferer_bridge()

static void get_transfer_parties_transferer_bridge ( struct ast_bridge transferer_bridge,
struct ast_bridge other_bridge,
struct ast_channel transferer,
struct ast_channel **  transferer_peer,
struct ast_channel **  other_party 
)
static

Get the transferee and transfer target when the transferer is in a bridge with one of the desired parties.

Parameters
transferer_bridgeThe bridge the transferer is in
other_bridgeThe bridge the transferer is not in. May be NULL.
transfererThe transferer party
[out]transferer_peerThe party that is in the bridge with the transferer
[out]other_partyThe party that is in the other_bridge

Definition at line 1609 of file bridge_basic.c.

1612{
1613 *transferer_peer = ast_bridge_peer(transferer_bridge, transferer);
1614 get_transfer_party_non_transferer_bridge(other_bridge, other_party);
1615}
struct ast_channel * ast_bridge_peer(struct ast_bridge *bridge, struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: bridge.c:4075

References ast_bridge_peer(), and get_transfer_party_non_transferer_bridge().

Referenced by get_transfer_parties().

◆ get_transfer_party_non_transferer_bridge()

static void get_transfer_party_non_transferer_bridge ( struct ast_bridge bridge,
struct ast_channel **  party 
)
static

Get a desired transfer party for a bridge the transferer is not in.

Parameters
bridgeThe bridge to get the party from. May be NULL.
[out]partyThe lone channel in the bridge. Will be set NULL if bridge is NULL or multiple parties are present.

Definition at line 1589 of file bridge_basic.c.

1591{
1592 if (bridge && bridge->num_channels == 1) {
1593 *party = ast_channel_ref(AST_LIST_FIRST(&bridge->channels)->chan);
1594 } else {
1595 *party = NULL;
1596 }
1597}
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
unsigned int num_channels
Definition: bridge.h:373

References ast_channel_ref, AST_LIST_FIRST, ast_bridge::channels, NULL, and ast_bridge::num_channels.

Referenced by get_transfer_parties(), and get_transfer_parties_transferer_bridge().

◆ grab_transfer()

static int grab_transfer ( struct ast_channel chan,
char *  exten,
size_t  exten_len,
const char *  context 
)
static

Helper function that presents dialtone and grabs extension.

Return values
0on success
-1on failure

Definition at line 3180 of file bridge_basic.c.

3181{
3182 int res;
3183 int digit_timeout;
3184 int attempts = 0;
3185 int max_attempts;
3186 struct ast_features_xfer_config *xfer_cfg;
3187 char *announce_sound, *retry_sound, *invalid_sound;
3188 const char *extenoverride;
3189
3190 ast_channel_lock(chan);
3191 extenoverride = get_transfer_exten(chan, NULL);
3192
3193 if (!ast_strlen_zero(extenoverride)) {
3194 int extenres = ast_exists_extension(chan, context, extenoverride, 1,
3195 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)) ? 1 : 0;
3196 if (extenres) {
3197 ast_copy_string(exten, extenoverride, exten_len);
3198 ast_channel_unlock(chan);
3199 ast_verb(3, "Transfering call to '%s@%s'", exten, context);
3200 return 0;
3201 }
3202 ast_log(LOG_WARNING, "Override extension '%s' does not exist in context '%s'\n", extenoverride, context);
3203 /* since we didn't get a valid extension from the channel, fall back and grab it from the user as usual now */
3204 }
3205
3206 xfer_cfg = ast_get_chan_features_xfer_config(chan);
3207 if (!xfer_cfg) {
3208 ast_log(LOG_ERROR, "Channel %s: Unable to get transfer configuration\n",
3209 ast_channel_name(chan));
3210 ast_channel_unlock(chan);
3211 return -1;
3212 }
3213 digit_timeout = xfer_cfg->transferdigittimeout * 1000;
3214 max_attempts = xfer_cfg->transferdialattempts;
3215 announce_sound = ast_strdupa(xfer_cfg->transferannouncesound);
3216 retry_sound = ast_strdupa(xfer_cfg->transferretrysound);
3217 invalid_sound = ast_strdupa(xfer_cfg->transferinvalidsound);
3218 ao2_ref(xfer_cfg, -1);
3219 ast_channel_unlock(chan);
3220
3221 /* Play the simple "transfer" prompt out and wait */
3222 if (!ast_strlen_zero(announce_sound)) {
3223 res = ast_stream_and_wait(chan, announce_sound, AST_DIGIT_ANY);
3224 ast_stopstream(chan);
3225 if (res < 0) {
3226 /* Hangup or error */
3227 return -1;
3228 }
3229 if (res) {
3230 /* Store the DTMF digit that interrupted playback of the file. */
3231 exten[0] = res;
3232 }
3233 }
3234
3235 /* Drop to dialtone so they can enter the extension they want to transfer to */
3236 do {
3237 ++attempts;
3238
3239 ast_test_suite_event_notify("TRANSFER_BEGIN_DIAL",
3240 "Channel: %s\r\n"
3241 "Attempt: %d",
3242 ast_channel_name(chan), attempts);
3243 res = ast_app_dtget(chan, context, exten, exten_len, exten_len - 1, digit_timeout);
3244 ast_test_suite_event_notify("TRANSFER_DIALLED",
3245 "Channel: %s\r\n"
3246 "Attempt: %d\r\n"
3247 "Dialled: %s\r\n"
3248 "Result: %s",
3249 ast_channel_name(chan), attempts, exten, res > 0 ? "Success" : "Failure");
3250 if (res < 0) {
3251 /* Hangup or error */
3252 res = -1;
3253 } else if (!res) {
3254 /* 0 for invalid extension dialed. */
3255 if (ast_strlen_zero(exten)) {
3256 ast_verb(3, "Channel %s: Dialed no digits.\n", ast_channel_name(chan));
3257 } else {
3258 ast_verb(3, "Channel %s: Dialed '%s@%s' does not exist.\n",
3259 ast_channel_name(chan), exten, context);
3260 }
3261 if (attempts < max_attempts) {
3262 ast_stream_and_wait(chan, retry_sound, AST_DIGIT_NONE);
3263 } else {
3264 ast_stream_and_wait(chan, invalid_sound, AST_DIGIT_NONE);
3265 }
3266 memset(exten, 0, exten_len);
3267 res = 1;
3268 } else {
3269 /* Dialed extension is valid. */
3270 res = 0;
3271 }
3272 } while (res > 0 && attempts < max_attempts);
3273
3274 ast_test_suite_event_notify("TRANSFER_DIAL_FINAL",
3275 "Channel: %s\r\n"
3276 "Result: %s",
3277 ast_channel_name(chan), res == 0 ? "Success" : "Failure");
3278
3279 return res ? -1 : 0;
3280}
static const char * get_transfer_exten(struct ast_channel *transferer, const char *exten)
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:222
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:1878
#define AST_DIGIT_NONE
Definition: file.h:47
#define AST_DIGIT_ANY
Definition: file.h:48
int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
Present a dialtone and collect a certain length extension.
Definition: main/app.c:138
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
const ast_string_field transferannouncesound
Number structure.
Definition: app_followme.c:154
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:189

References ao2_ref, ast_app_dtget(), ast_channel_caller(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_copy_string(), AST_DIGIT_ANY, AST_DIGIT_NONE, ast_exists_extension(), ast_get_chan_features_xfer_config(), ast_log, ast_stopstream(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_test_suite_event_notify, ast_verb, voicemailpwcheck::context, get_transfer_exten(), LOG_ERROR, LOG_WARNING, NULL, S_COR, ast_features_xfer_config::transferannouncesound, ast_features_xfer_config::transferdialattempts, ast_features_xfer_config::transferdigittimeout, ast_features_xfer_config::transferinvalidsound, and ast_features_xfer_config::transferretrysound.

Referenced by feature_attended_transfer(), and feature_blind_transfer().

◆ hesitant_enter()

static int hesitant_enter ( struct attended_transfer_properties props)
static

◆ hesitant_exit()

static enum attended_transfer_state hesitant_exit ( struct attended_transfer_properties props,
enum attended_transfer_stimulus  stimulus 
)
static

Definition at line 2169 of file bridge_basic.c.

2171{
2172 switch (stimulus) {
2174 play_failsound(props->transferer);
2175 publish_transfer_fail(props);
2176 return TRANSFER_FAIL;
2183 case STIMULUS_TIMEOUT:
2185 play_failsound(props->transferer);
2186 return TRANSFER_RESUME;
2188 return TRANSFER_THREEWAY;
2190 hold(props->transferer);
2192 case STIMULUS_NONE:
2195 default:
2196 ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2197 stimulus_strs[stimulus], state_properties[props->state].state_name);
2198 return props->state;
2199 }
2200}

References ast_log, attended_transfer_properties::atxferdropcall, hold(), LOG_WARNING, play_failsound(), publish_transfer_fail(), attended_transfer_properties::state, attended_transfer_state_properties::state_name, state_properties, STIMULUS_DTMF_ATXFER_ABORT, STIMULUS_DTMF_ATXFER_COMPLETE, STIMULUS_DTMF_ATXFER_SWAP, STIMULUS_DTMF_ATXFER_THREEWAY, STIMULUS_NONE, STIMULUS_RECALL_TARGET_ANSWER, STIMULUS_RECALL_TARGET_HANGUP, stimulus_strs, STIMULUS_TIMEOUT, STIMULUS_TRANSFER_TARGET_ANSWER, STIMULUS_TRANSFER_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, STIMULUS_TRANSFERER_HANGUP, TRANSFER_BLOND, TRANSFER_BLOND_NONFINAL, TRANSFER_CALLING_TARGET, TRANSFER_DOUBLECHECKING, TRANSFER_FAIL, TRANSFER_RESUME, TRANSFER_THREEWAY, and attended_transfer_properties::transferer.

◆ hold()

static void hold ( struct ast_channel chan)
static

Helper method to place a channel in a bridge on hold.

Definition at line 1788 of file bridge_basic.c.

1789{
1790 struct ast_bridge_channel *bridge_channel;
1791
1792 if (!chan) {
1793 return;
1794 }
1795
1797 bridge_channel = ast_channel_get_bridge_channel(chan);
1799
1800 if (bridge_channel) {
1801 ast_bridge_channel_write_hold(bridge_channel, NULL);
1802 ao2_ref(bridge_channel, -1);
1803 }
1804}

References ao2_ref, ast_bridge_channel_write_hold(), ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, ast_bridge_channel::chan, and NULL.

Referenced by bridge_hold(), consulting_exit(), double_checking_exit(), hesitant_exit(), and sla_hold_str().

◆ init_details()

static void init_details ( struct personality_details details,
enum bridge_basic_personality_type  type 
)
static

Definition at line 3619 of file bridge_basic.c.

3621{
3622 switch (type) {
3625 details->bridge_flags = NORMAL_FLAGS;
3627 break;
3630 details->bridge_flags = TRANSFER_FLAGS;
3631 break;
3632 default:
3633 ast_log(LOG_WARNING, "Asked to initialize unexpected basic bridge personality type.\n");
3634 break;
3635 }
3636}
#define TRANSFER_FLAGS
Definition: bridge_basic.c:54
static void on_personality_change_normal(struct ast_bridge *bridge)

References ast_log, BRIDGE_BASIC_PERSONALITY_ATXFER, BRIDGE_BASIC_PERSONALITY_NORMAL, personality_details::bridge_flags, LOG_WARNING, NORMAL_FLAGS, personality_details::on_personality_change, on_personality_change_normal(), personality_atxfer_v_table, personality_normal_v_table, TRANSFER_FLAGS, type, and personality_details::v_table.

Referenced by bridge_basic_personality_alloc().

◆ on_personality_change_normal()

static void on_personality_change_normal ( struct ast_bridge bridge)
static

Definition at line 3607 of file bridge_basic.c.

3608{
3609 struct ast_bridge_channel *iter;
3610
3612 if (add_normal_hooks(bridge, iter)) {
3613 ast_log(LOG_WARNING, "Unable to set up bridge hooks for channel %s. Features may not work properly\n",
3614 ast_channel_name(iter->chan));
3615 }
3616 }
3617}

References add_normal_hooks(), ast_channel_name(), AST_LIST_TRAVERSE, ast_log, ast_bridge_channel::bridge, ast_bridge_channel::chan, ast_bridge::channels, and LOG_WARNING.

Referenced by init_details().

◆ personality_destructor()

static void personality_destructor ( void *  obj)
static

Definition at line 3597 of file bridge_basic.c.

3598{
3599 struct bridge_basic_personality *personality = obj;
3600 int i;
3601
3602 for (i = 0; i < BRIDGE_BASIC_PERSONALITY_END; ++i) {
3603 ao2_cleanup(personality->details[i].pvt);
3604 }
3605}

References ao2_cleanup, BRIDGE_BASIC_PERSONALITY_END, bridge_basic_personality::details, and personality_details::pvt.

Referenced by bridge_basic_personality_alloc().

◆ play_failsound()

static void play_failsound ( struct ast_channel chan)
static

Helper method to play a fail sound on a channel in a bridge.

Parameters
chanThe channel to play the fail sound to

Definition at line 1752 of file bridge_basic.c.

1753{
1754 char *sound;
1755
1756 ast_channel_lock(chan);
1758 ast_channel_unlock(chan);
1759
1760 if (sound) {
1761 play_sound(chan, sound);
1762 ast_free(sound);
1763 }
1764}
char * ast_get_chan_features_xferfailsound(struct ast_channel *chan)
Get the transfer configuration option xferfailsound.

References ast_channel_lock, ast_channel_unlock, ast_free, ast_get_chan_features_xferfailsound(), ast_bridge_channel::chan, and play_sound().

Referenced by calling_target_exit(), consulting_exit(), double_checking_exit(), and hesitant_exit().

◆ play_sound()

static void play_sound ( struct ast_channel chan,
const char *  sound 
)
static

Helper method to play a sound on a channel in a bridge.

Parameters
chanThe channel to play the sound to
soundThe sound to play

Definition at line 1733 of file bridge_basic.c.

1734{
1735 struct ast_bridge_channel *bridge_channel;
1736
1738 bridge_channel = ast_channel_get_bridge_channel(chan);
1740
1741 if (bridge_channel) {
1742 ast_bridge_channel_queue_playfile(bridge_channel, NULL, sound, NULL);
1743 ao2_ref(bridge_channel, -1);
1744 }
1745}
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.

References ao2_ref, ast_bridge_channel_queue_playfile(), ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, ast_bridge_channel::chan, and NULL.

Referenced by complete_enter(), play_failsound(), and threeway_enter().

◆ publish_transfer_fail()

static void publish_transfer_fail ( struct attended_transfer_properties props)
static

Send a stasis publication for a failed attended transfer.

Definition at line 1708 of file bridge_basic.c.

1709{
1710 struct ast_attended_transfer_message *transfer_msg;
1711
1712 transfer_msg = ast_attended_transfer_message_create(0, props->transferer,
1713 props->transferee_bridge, props->transferer, props->target_bridge,
1714 NULL, NULL);
1715
1716 if (!transfer_msg) {
1717 ast_log(LOG_ERROR, "Unable to publish failed transfer from %s\n",
1719 return;
1720 }
1721
1722 transfer_msg->result = AST_BRIDGE_TRANSFER_FAIL;
1724 ao2_cleanup(transfer_msg);
1725}
@ AST_BRIDGE_TRANSFER_FAIL
Definition: bridge.h:1106
void ast_bridge_publish_attended_transfer(struct ast_attended_transfer_message *transfer_msg)
Publish an attended transfer.
struct ast_attended_transfer_message * ast_attended_transfer_message_create(int is_external, struct ast_channel *to_transferee, struct ast_bridge *transferee_bridge, struct ast_channel *to_transfer_target, struct ast_bridge *target_bridge, struct ast_channel *transferee, struct ast_channel *transfer_target)
Create an Attended transfer message to be published.
Message representing attended transfer.
enum ast_transfer_result result

References ao2_cleanup, ast_attended_transfer_message_create(), ast_bridge_publish_attended_transfer(), AST_BRIDGE_TRANSFER_FAIL, ast_channel_name(), ast_log, LOG_ERROR, NULL, ast_attended_transfer_message::result, attended_transfer_properties::target_bridge, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer.

Referenced by calling_target_exit(), double_checking_exit(), and hesitant_exit().

◆ publish_transfer_success()

static void publish_transfer_success ( struct attended_transfer_properties props,
struct ast_channel transferee_channel,
struct ast_channel target_channel 
)
static

Send a stasis publication for a successful attended transfer.

Definition at line 1661 of file bridge_basic.c.

1663{
1664 struct ast_attended_transfer_message *transfer_msg;
1665
1666 transfer_msg = ast_attended_transfer_message_create(0, props->transferer,
1667 props->transferee_bridge, props->transferer, props->target_bridge,
1668 transferee_channel, target_channel);
1669
1670 if (!transfer_msg) {
1671 ast_log(LOG_ERROR, "Unable to publish successful attended transfer from %s\n",
1673 return;
1674 }
1675
1678 ao2_cleanup(transfer_msg);
1679}
int ast_attended_transfer_message_add_merge(struct ast_attended_transfer_message *transfer_msg, struct ast_bridge *final_bridge)
Add details for a bridge merge to an attended transfer message.

References ao2_cleanup, ast_attended_transfer_message_add_merge(), ast_attended_transfer_message_create(), ast_bridge_publish_attended_transfer(), ast_channel_name(), ast_log, LOG_ERROR, attended_transfer_properties::target_bridge, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer.

Referenced by blond_enter(), and complete_enter().

◆ publish_transfer_threeway()

static void publish_transfer_threeway ( struct attended_transfer_properties props,
struct ast_channel transferee_channel,
struct ast_channel target_channel 
)
static

Send a stasis publication for an attended transfer that ends in a threeway call.

Definition at line 1684 of file bridge_basic.c.

1686{
1687 struct ast_attended_transfer_message *transfer_msg;
1688
1689 transfer_msg = ast_attended_transfer_message_create(0, props->transferer,
1690 props->transferee_bridge, props->transferer, props->target_bridge,
1691 transferee_channel, target_channel);
1692
1693 if (!transfer_msg) {
1694 ast_log(LOG_ERROR, "Unable to publish successful three-way transfer from %s\n",
1696 return;
1697 }
1698
1700 props->transferee_bridge);
1702 ao2_cleanup(transfer_msg);
1703}
int ast_attended_transfer_message_add_threeway(struct ast_attended_transfer_message *transfer_msg, struct ast_channel *survivor_channel, struct ast_bridge *survivor_bridge)
Add details for an attended transfer that was resolved as a three-way call.

References ao2_cleanup, ast_attended_transfer_message_add_threeway(), ast_attended_transfer_message_create(), ast_bridge_publish_attended_transfer(), ast_channel_name(), ast_log, LOG_ERROR, attended_transfer_properties::target_bridge, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer.

Referenced by threeway_enter().

◆ rebridge_enter()

static int rebridge_enter ( struct attended_transfer_properties props)
static

◆ recall_callback()

static void recall_callback ( struct ast_dial dial)
static

Dial callback when attempting to recall the original transferer channel.

This is how we can monitor if the recall target has answered or has hung up. If one of the two is detected, then an appropriate stimulus is sent to the attended transfer monitor thread.

Definition at line 2410 of file bridge_basic.c.

2411{
2413
2414 switch (ast_dial_state(dial)) {
2415 default:
2421 /* Failure cases */
2423 break;
2428 /* Don't care about these cases */
2429 break;
2431 /* We struck gold! */
2434 break;
2435 }
2436}
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
Return state of dial.
Definition: dial.c:1008
@ AST_DIAL_RESULT_FAILED
Definition: dial.h:56
@ AST_DIAL_RESULT_HANGUP
Definition: dial.h:63
@ AST_DIAL_RESULT_INVALID
Definition: dial.h:55
@ AST_DIAL_RESULT_ANSWERED
Definition: dial.h:61
@ AST_DIAL_RESULT_TIMEOUT
Definition: dial.h:62
@ AST_DIAL_RESULT_TRYING
Definition: dial.h:57
@ AST_DIAL_RESULT_PROGRESS
Definition: dial.h:59
@ AST_DIAL_RESULT_RINGING
Definition: dial.h:58
@ AST_DIAL_RESULT_PROCEEDING
Definition: dial.h:60
@ AST_DIAL_RESULT_UNANSWERED
Definition: dial.h:64
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition: dial.c:989
void * ast_dial_get_user_data(struct ast_dial *dial)
Return the user data on a dial structure.
Definition: dial.c:1279

References ast_dial_answered_steal(), ast_dial_get_user_data(), AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_FAILED, AST_DIAL_RESULT_HANGUP, AST_DIAL_RESULT_INVALID, AST_DIAL_RESULT_PROCEEDING, AST_DIAL_RESULT_PROGRESS, AST_DIAL_RESULT_RINGING, AST_DIAL_RESULT_TIMEOUT, AST_DIAL_RESULT_TRYING, AST_DIAL_RESULT_UNANSWERED, ast_dial_state(), attended_transfer_properties::dial, attended_transfer_properties::recall_target, stimulate_attended_transfer(), STIMULUS_RECALL_TARGET_ANSWER, and STIMULUS_RECALL_TARGET_HANGUP.

Referenced by recalling_enter().

◆ recall_pull()

static void recall_pull ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel,
struct attended_transfer_properties props 
)
static

Definition at line 2959 of file bridge_basic.c.

2960{
2961 if (self == props->target_bridge) {
2962 /* Once we're in the recall superstate, we no longer care about this bridge */
2963 return;
2964 }
2965
2966 if (bridge_channel->chan == props->recall_target) {
2968 return;
2969 }
2970
2971 if (self->num_channels == 0) {
2972 /* Empty bridge means all transferees are gone for sure */
2974 return;
2975 }
2976
2977 if (self->num_channels == 1) {
2978 struct ast_bridge_channel *target_bridge_channel;
2979
2980 if (!props->recall_target) {
2981 /* No recall target means that the pull happened on a transferee. If there's still
2982 * a channel left in the bridge, we don't need to send a stimulus
2983 */
2984 return;
2985 }
2986
2988 target_bridge_channel = ast_channel_get_bridge_channel(props->recall_target);
2990
2991 if (target_bridge_channel) {
2992 if (AST_LIST_FIRST(&self->channels) == target_bridge_channel) {
2994 }
2995 ao2_ref(target_bridge_channel, -1);
2996 }
2997 }
2998}

References ao2_ref, ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, AST_LIST_FIRST, ast_bridge_channel::chan, ast_bridge::channels, ast_bridge::num_channels, attended_transfer_properties::recall_target, stimulate_attended_transfer(), STIMULUS_RECALL_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, and attended_transfer_properties::target_bridge.

Referenced by bridge_personality_atxfer_pull().

◆ recalling_enter()

static int recalling_enter ( struct attended_transfer_properties props)
static

Definition at line 2475 of file bridge_basic.c.

2476{
2478 struct ast_channel *recall;
2479
2480 if (!cap) {
2481 return -1;
2482 }
2483
2485
2486 /* When we dial the transfer target, since we are communicating
2487 * with a local channel, we can place the local channel in a bridge
2488 * and then call out to it. When recalling the transferer, though, we
2489 * have to use the dialing API because the channel is not local.
2490 */
2491 props->dial = ast_dial_create();
2492 if (!props->dial) {
2493 return -1;
2494 }
2495
2496 if (ast_dial_append(props->dial, props->transferer_type, props->transferer_addr, NULL)) {
2497 return -1;
2498 }
2499
2500 if (ast_dial_prerun(props->dial, NULL, cap)) {
2501 return -1;
2502 }
2503
2504 /*
2505 * Setup callid, variables, datastores, accountcode, peeraccount,
2506 * COLP, and CLID on the recalled transferrer.
2507 */
2508 recall = ast_dial_get_channel(props->dial, 0);
2509 if (!recall) {
2510 return -1;
2511 }
2512 ast_channel_lock_both(recall, props->transferer);
2513
2517 &props->original_transferer_colp);
2518
2520 ast_channel_unlock(recall);
2522
2524
2525 ao2_ref(props, +1);
2526 ast_dial_set_user_data(props->dial, props);
2527
2528 if (ast_dial_run(props->dial, NULL, 1) == AST_DIAL_RESULT_FAILED) {
2529 ao2_ref(props, -1);
2530 return -1;
2531 }
2532
2534 return 0;
2535}
static void bridge_ringing(struct ast_bridge *bridge)
Helper method to send a ringing indication to all channels in a bridge.
static void recall_callback(struct ast_dial *dial)
Dial callback when attempting to recall the original transferer channel.
static void common_recall_channel_setup(struct ast_channel *recall, struct ast_channel *transferer)
void ast_party_caller_copy(struct ast_party_caller *dest, const struct ast_party_caller *src)
Copy the source caller information to the destination caller.
Definition: channel.c:2005
void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
Set a callback for state changes.
Definition: dial.c:1269
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Append a channel.
Definition: dial.c:280
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:223
void ast_dial_set_user_data(struct ast_dial *dial, void *user_data)
Set user data on a dial structure.
Definition: dial.c:1274
int ast_dial_prerun(struct ast_dial *dial, struct ast_channel *chan, struct ast_format_cap *cap)
Request all appended channels, but do not dial.
Definition: dial.c:431
enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
Execute dialing synchronously or asynchronously.
Definition: dial.c:935
struct ast_channel * ast_dial_get_channel(struct ast_dial *dial, int num)
Get the dialing channel, if prerun has been executed.
Definition: dial.c:1258
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
const ast_string_field transferer_type
const ast_string_field transferer_addr
#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 ao2_cleanup, ao2_ref, ast_channel_caller(), ast_channel_connected(), ast_channel_lock_both, ast_channel_unlock, ast_dial_append(), ast_dial_create(), ast_dial_get_channel(), ast_dial_prerun(), AST_DIAL_RESULT_FAILED, ast_dial_run(), ast_dial_set_state_callback(), ast_dial_set_user_data(), ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_slin, ast_party_caller_copy(), ast_party_connected_line_copy(), bridge_ringing(), common_recall_channel_setup(), attended_transfer_properties::dial, NULL, attended_transfer_properties::original_transferer_colp, RAII_VAR, recall_callback(), attended_transfer_properties::transferee_bridge, attended_transfer_properties::transferer, attended_transfer_properties::transferer_addr, and attended_transfer_properties::transferer_type.

◆ recalling_exit()

static enum attended_transfer_state recalling_exit ( struct attended_transfer_properties props,
enum attended_transfer_stimulus  stimulus 
)
static

Definition at line 2537 of file bridge_basic.c.

2539{
2540 /* No matter what the outcome was, we need to kill off the dial */
2541 ast_dial_join(props->dial);
2542 ast_dial_destroy(props->dial);
2543 props->dial = NULL;
2544 /* This reference is the one we incremented for the dial state callback (recall_callback) to use */
2545 ao2_ref(props, -1);
2546
2547 switch (stimulus) {
2549 return TRANSFER_FAIL;
2550 case STIMULUS_TIMEOUT:
2552 ++props->retry_attempts;
2553 if (props->retry_attempts >= props->atxfercallbackretries) {
2554 return TRANSFER_FAIL;
2555 }
2556 if (props->atxferloopdelay) {
2558 }
2559 return TRANSFER_RETRANSFER;
2561 /* Setting this datastore up will allow the transferer to have all of his
2562 * call features set up automatically when the bridge changes back to a
2563 * normal personality
2564 */
2569 ast_hangup(props->recall_target);
2571 return TRANSFER_FAIL;
2572 }
2573 return TRANSFER_RESUME;
2574 case STIMULUS_NONE:
2582 default:
2583 ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2584 stimulus_strs[stimulus], state_properties[props->state].state_name);
2585 return props->state;
2586 }
2587}
enum ast_dial_result ast_dial_join(struct ast_dial *dial)
Cancel async thread.
Definition: dial.c:1017
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1091

References ao2_ref, ast_bridge_features_ds_set(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_channel_ref, ast_channel_unref, ast_dial_destroy(), ast_dial_join(), ast_hangup(), ast_log, attended_transfer_properties::atxfercallbackretries, attended_transfer_properties::atxferloopdelay, attended_transfer_properties::dial, LOG_WARNING, NULL, attended_transfer_properties::recall_target, attended_transfer_properties::retry_attempts, attended_transfer_properties::state, attended_transfer_state_properties::state_name, state_properties, STIMULUS_DTMF_ATXFER_ABORT, STIMULUS_DTMF_ATXFER_COMPLETE, STIMULUS_DTMF_ATXFER_SWAP, STIMULUS_DTMF_ATXFER_THREEWAY, STIMULUS_NONE, STIMULUS_RECALL_TARGET_ANSWER, STIMULUS_RECALL_TARGET_HANGUP, stimulus_strs, STIMULUS_TIMEOUT, STIMULUS_TRANSFER_TARGET_ANSWER, STIMULUS_TRANSFER_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, STIMULUS_TRANSFERER_HANGUP, TRANSFER_FAIL, TRANSFER_RESUME, TRANSFER_RETRANSFER, TRANSFER_WAIT_TO_RETRANSFER, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer_features.

◆ remove_attended_transfer_stimulus()

static void remove_attended_transfer_stimulus ( struct attended_transfer_properties props,
enum attended_transfer_stimulus  stimulus 
)
static

Definition at line 1566 of file bridge_basic.c.

1568{
1569 struct stimulus_list *list;
1570
1571 ao2_lock(props);
1573 if (list->stimulus == stimulus) {
1575 ast_free(list);
1576 break;
1577 }
1578 }
1580 ao2_unlock(props);
1581}
#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 attended_transfer_stimulus stimulus

References ao2_lock, ao2_unlock, ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, stimulus_list::next, stimulus_list::stimulus, and attended_transfer_properties::stimulus_queue.

Referenced by blond_nonfinal_exit().

◆ remove_hooks_on_personality_change()

static void remove_hooks_on_personality_change ( struct ast_bridge bridge)
static

Remove appropriate hooks when basic bridge personality changes.

Hooks that have the AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE flag set will be removed from all bridge channels in the bridge.

Parameters
bridgeBasic bridge undergoing personality change

Definition at line 719 of file bridge_basic.c.

720{
721 struct ast_bridge_channel *iter;
722
726 }
727}
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:3501
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
#define ast_bridge_channel_lock(bridge_channel)
Lock the bridge_channel.

References ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_bridge_features_remove(), AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE, AST_LIST_TRAVERSE, ast_bridge_channel::bridge, ast_bridge::channels, ast_bridge_channel::features, lock, and SCOPED_LOCK.

Referenced by bridge_basic_change_personality().

◆ resume_enter()

static int resume_enter ( struct attended_transfer_properties props)
static

Definition at line 2209 of file bridge_basic.c.

2210{
2211 return 0;
2212}

◆ retransfer_enter()

static int retransfer_enter ( struct attended_transfer_properties props)
static

Definition at line 2623 of file bridge_basic.c.

2624{
2626 char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
2627 int cause;
2628
2629 if (!cap) {
2630 return -1;
2631 }
2632
2633 snprintf(destination, sizeof(destination), "%s@%s", props->exten, props->context);
2634
2636
2637 /* Get a channel that is the destination we wish to call */
2638 props->recall_target = ast_request("Local", cap, NULL, NULL, destination, &cause);
2639 if (!props->recall_target) {
2640 ast_log(LOG_ERROR, "Unable to request outbound channel for recall target\n");
2641 return -1;
2642 }
2643
2644 if (attach_framehook(props, props->recall_target)) {
2645 ast_log(LOG_ERROR, "Unable to attach framehook to recall target\n");
2646 ast_hangup(props->recall_target);
2647 props->recall_target = NULL;
2648 return -1;
2649 }