Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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 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 774 of file bridge_basic.c.

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

1933  {
1934  /*! This state requires that the timer be reset when entering the state */
1936  /*! This state's timer uses atxferloopdelay */
1938  /*! This state's timer uses atxfernoanswertimeout */
1940  /*! This state has a time limit associated with it */
1943  /*! This state does not transition to any other states */
1944  TRANSFER_STATE_FLAG_TERMINAL = (1 << 3),
1945 };
@ 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 1236 of file bridge_basic.c.

1236  {
1237  /*! No stimulus. This literally can never happen. */
1238  STIMULUS_NONE,
1239  /*! All of the transferee channels have been hung up. */
1241  /*! The transferer has hung up. */
1243  /*! The transfer target channel has hung up. */
1245  /*! The transfer target channel has answered. */
1247  /*! The recall target channel has hung up. */
1249  /*! The recall target channel has answered. */
1251  /*! The current state's timer has expired. */
1253  /*! The transferer pressed the abort DTMF sequence. */
1255  /*! The transferer pressed the complete DTMF sequence. */
1257  /*! The transferer pressed the three-way DTMF sequence. */
1259  /*! The transferer pressed the swap DTMF sequence. */
1261 };
@ 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 737 of file bridge_basic.c.

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

◆ 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 641 of file bridge_basic.c.

642 {
643  return ast_bridge_hangup_hook(bridge_channel->features, basic_hangup_hook,
645  || bridge_basic_setup_features(bridge_channel);
646 }
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:631
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 3119 of file bridge_basic.c.

3120 {
3121  const char *atxfer_abort;
3122  const char *atxfer_threeway;
3123  const char *atxfer_complete;
3124  const char *atxfer_swap;
3125  struct ast_features_xfer_config *xfer_cfg;
3126  SCOPED_CHANNELLOCK(lock, chan);
3127 
3128  xfer_cfg = ast_get_chan_features_xfer_config(chan);
3129  if (!xfer_cfg) {
3130  return -1;
3131  }
3132  if (attended_transfer) {
3133  atxfer_abort = ast_strdupa(S_OR(attended_transfer->abort, xfer_cfg->atxferabort));
3134  atxfer_threeway = ast_strdupa(S_OR(attended_transfer->threeway, xfer_cfg->atxferthreeway));
3135  atxfer_complete = ast_strdupa(S_OR(attended_transfer->complete, xfer_cfg->atxfercomplete));
3136  atxfer_swap = ast_strdupa(S_OR(attended_transfer->swap, xfer_cfg->atxferswap));
3137  } else {
3138  atxfer_abort = ast_strdupa(xfer_cfg->atxferabort);
3141  atxfer_swap = ast_strdupa(xfer_cfg->atxferswap);
3142  }
3143  ao2_ref(xfer_cfg, -1);
3144 
3150 }
ast_mutex_t lock
Definition: app_meetme.c:1093
#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:617
#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 3614 of file bridge_basic.c.

3615 {
3616  struct ast_bridge *bridge;
3617 
3618  bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table);
3619  bridge = bridge_base_init(bridge,
3622  bridge = bridge_basic_personality_alloc(bridge);
3623  bridge = bridge_register(bridge);
3624  return bridge;
3625 }
@ 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_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_register(struct ast_bridge *bridge)
Register the new bridge with the system.
Definition: bridge.c:691
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 3627 of file bridge_basic.c.

3628 {
3630  struct bridge_basic_personality *personality = bridge->personality;
3631 
3632  personality->details[personality->current].bridge_flags |= flags;
3633  ast_set_flag(&bridge->feature_flags, flags);
3634 }
#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:581
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:2398
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 }
struct ast_flags * ast_bridge_features_ds_get(struct ast_channel *chan)
Get DTMF feature flags from the channel.
Definition: bridge_basic.c:268
static int dtmf_features_flags_to_string(struct ast_flags *feature_flags, char *buffer, size_t buffer_size)
Definition: bridge_basic.c:133
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define ast_channel_unlock(chan)
Definition: channel.h:2923
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(), and parked_call_retrieve_enable_features().

◆ 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 3636 of file bridge_basic.c.

3637 {
3638  /* Setup bridge basic subclass v_table. */
3640  ast_bridge_basic_v_table.name = "basic";
3644 
3645  /*
3646  * Personality vtables don't have the same rules as
3647  * normal bridge vtables. These vtable functions are
3648  * used as alterations to the ast_bridge_basic_v_table
3649  * method functionality and are checked for NULL before
3650  * calling.
3651  */
3652  personality_normal_v_table.name = "normal";
3654 
3655  personality_atxfer_v_table.name = "attended transfer";
3658 
3661 }
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:688
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:703
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:662
static int bridge_basic_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
Definition: bridge_basic.c:671
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 3096 of file bridge_basic.c.

3097 {
3098  struct ast_framehook_interface target_interface = {
3100  .event_cb = transfer_target_framehook_cb,
3102  .consume_cb = transfer_target_framehook_consume,
3103  .disable_inheritance = 1,
3104  };
3105 
3106  ao2_ref(props, +1);
3107  target_interface.data = props;
3108 
3109  ast_channel_lock(channel);
3110  props->target_framehook_id = ast_framehook_attach(channel, &target_interface);
3111  ast_channel_unlock(channel);
3112  if (props->target_framehook_id == -1) {
3113  ao2_ref(props, -1);
3114  return -1;
3115  }
3116  return 0;
3117 }
static void transfer_target_framehook_destroy_cb(void *data)
static int transfer_target_framehook_consume(void *data, enum ast_frame_type type)
Callback function which informs upstream if we are consuming a frame of a specific type.
static 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.
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 3042 of file bridge_basic.c.

3043 {
3044  struct attended_transfer_properties *props = data;
3045  ast_callid callid;
3046 
3047  /*
3048  * Set thread callid to the transferer's callid because we
3049  * are doing all this on that channel's behalf.
3050  */
3051  ast_channel_lock(props->transferer);
3052  callid = ast_channel_callid(props->transferer);
3054  if (callid) {
3056  }
3057 
3058  for (;;) {
3059  enum attended_transfer_stimulus stimulus;
3060 
3061  ast_debug(1, "About to enter state %s for attended transfer %p\n", state_properties[props->state].state_name, props);
3062 
3063  if (state_properties[props->state].enter &&
3064  state_properties[props->state].enter(props)) {
3065  ast_log(LOG_ERROR, "State %s enter function returned an error for attended transfer %p\n",
3066  state_properties[props->state].state_name, props);
3067  break;
3068  }
3069 
3071  ast_debug(1, "State %s is a terminal state. Ending attended transfer %p\n",
3072  state_properties[props->state].state_name, props);
3073  break;
3074  }
3075 
3076  stimulus = wait_for_stimulus(props);
3077 
3078  ast_debug(1, "Received stimulus %s on attended transfer %p\n", stimulus_strs[stimulus], props);
3079 
3081 
3082  props->state = state_properties[props->state].exit(props, stimulus);
3083 
3084  ast_debug(1, "Told to enter state %s exit on attended transfer %p\n", state_properties[props->state].state_name, props);
3085  }
3086 
3088 
3089  if (callid) {
3091  }
3092 
3093  return NULL;
3094 }
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:2070
unsigned int ast_callid
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
Definition: logger.c:2089
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:734

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 1409 of file bridge_basic.c.

1411 {
1412  struct attended_transfer_properties *props;
1413  char *tech;
1414  char *addr;
1415  char *serial;
1416  struct ast_features_xfer_config *xfer_cfg;
1417  struct ast_flags *transferer_features;
1418 
1419  props = ao2_alloc(sizeof(*props), attended_transfer_properties_destructor);
1420  if (!props) {
1421  ast_log(LOG_ERROR, "Unable to create props - channel %s, context %s\n",
1422  ast_channel_name(transferer), context);
1423  return NULL;
1424  }
1425 
1426  ast_cond_init(&props->cond, NULL);
1427 
1428  if (ast_string_field_init(props, 64)) {
1429  ast_log(LOG_ERROR, "Unable to initialize prop fields - channel %s, context %s\n",
1430  ast_channel_name(transferer), context);
1431  ao2_ref(props, -1);
1432  return NULL;
1433  }
1434 
1435  props->target_framehook_id = -1;
1436  props->transferer = ast_channel_ref(transferer);
1437 
1438  ast_channel_lock(props->transferer);
1439  xfer_cfg = ast_get_chan_features_xfer_config(props->transferer);
1440  if (!xfer_cfg) {
1441  ast_log(LOG_ERROR, "Unable to get transfer configuration from channel %s\n", ast_channel_name(props->transferer));
1443  ao2_ref(props, -1);
1444  return NULL;
1445  }
1446  transferer_features = ast_bridge_features_ds_get(props->transferer);
1447  if (transferer_features) {
1448  props->transferer_features = *transferer_features;
1449  }
1450  props->atxferdropcall = xfer_cfg->atxferdropcall;
1451  props->atxfercallbackretries = xfer_cfg->atxfercallbackretries;
1452  props->atxfernoanswertimeout = xfer_cfg->atxfernoanswertimeout;
1453  props->atxferloopdelay = xfer_cfg->atxferloopdelay;
1455  ast_string_field_set(props, xfersound, xfer_cfg->xfersound);
1456  ao2_ref(xfer_cfg, -1);
1457 
1458  /*
1459  * Save the transferee's party information for any recall calls.
1460  * This is the only piece of information needed that gets overwritten
1461  * on the transferer channel by the inital call to the transfer target.
1462  */
1465 
1466  tech = ast_strdupa(ast_channel_name(props->transferer));
1467  addr = strchr(tech, '/');
1468  if (!addr) {
1469  ast_log(LOG_ERROR, "Transferer channel name does not follow typical channel naming format (tech/address)\n");
1471  ao2_ref(props, -1);
1472  return NULL;
1473  }
1474  *addr++ = '\0';
1475  serial = strrchr(addr, '-');
1476  if (serial) {
1477  *serial = '\0';
1478  }
1479  ast_string_field_set(props, transferer_type, tech);
1480  ast_string_field_set(props, transferer_addr, addr);
1481 
1483 
1484  ast_debug(1, "Allocated attended transfer properties %p for transfer from %s\n",
1485  props, ast_channel_name(props->transferer));
1486  return props;
1487 }
#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)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
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:2025
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#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, 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 1353 of file bridge_basic.c.

1354 {
1355  struct attended_transfer_properties *props = obj;
1356 
1357  ast_debug(1, "Destroy attended transfer properties %p\n", props);
1358 
1359  ao2_cleanup(props->target_bridge);
1361  /* Use ast_channel_cleanup() instead of ast_channel_unref() for channels since they may be NULL */
1367  ast_cond_destroy(&props->cond);
1368 }
#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:2066
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
#define ast_cond_destroy(cond)
Definition: lock.h:200
#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 1508 of file bridge_basic.c.

1509 {
1510  ast_debug(1, "Shutting down attended transfer %p\n", props);
1511 
1512  if (props->transferee_bridge) {
1516  }
1517 
1518  if (props->target_bridge) {
1519  ast_bridge_destroy(props->target_bridge, 0);
1520  props->target_bridge = NULL;
1521  }
1522 
1523  if (props->transferer) {
1525  }
1526 
1527  clear_stimulus_queue(props);
1528 
1529  ao2_cleanup(props);
1530 }
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 2739 of file bridge_basic.c.

2740 {
2741  struct attended_transfer_properties *props = hook_pvt;
2742 
2743  ast_debug(1, "Transferer on attended transfer %p pressed abort sequence\n", props);
2745  return 0;
2746 }
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 2753 of file bridge_basic.c.

2754 {
2755  struct attended_transfer_properties *props = hook_pvt;
2756 
2757  ast_debug(1, "Transferer on attended transfer %p pressed complete sequence\n", props);
2759  return 0;
2760 }

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 2781 of file bridge_basic.c.

2782 {
2783  struct attended_transfer_properties *props = hook_pvt;
2784 
2785  ast_debug(1, "Transferer on attended transfer %p pressed swap sequence\n", props);
2787  return 0;
2788 }

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 2767 of file bridge_basic.c.

2768 {
2769  struct attended_transfer_properties *props = hook_pvt;
2770 
2771  ast_debug(1, "Transferer on attended transfer %p pressed threeway sequence\n", props);
2773  return 0;
2774 }

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 2795 of file bridge_basic.c.

2796 {
2797  struct attended_transfer_properties *props = hook_pvt;
2798 
2799  ast_debug(1, "Transferer on attended transfer %p hung up\n", props);
2801  return 0;
2802 }

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 3458 of file bridge_basic.c.

3460 {
3461  struct ast_channel *transferer_channel = user_data_wrapper->data;
3462 
3463  if (transfer_type == AST_BRIDGE_TRANSFER_MULTI_PARTY) {
3464  copy_caller_data(new_channel, transferer_channel);
3465  }
3466 }
@ 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.

◆ blond_enter()

static int blond_enter ( struct attended_transfer_properties props)
static

Definition at line 2322 of file bridge_basic.c.

2323 {
2324  struct ast_channel *transferee_channel;
2325  struct ast_channel *target_channel;
2326 
2328  &transferee_channel, &target_channel);
2329  bridge_merge(props->transferee_bridge, props->target_bridge, &props->transferer, 1);
2330  ringing(props->transfer_target);
2331  publish_transfer_success(props, transferee_channel, target_channel);
2332 
2333  ast_channel_cleanup(transferee_channel);
2334  ast_channel_cleanup(target_channel);
2335  return 0;
2336 }
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 2338 of file bridge_basic.c.

2339 {
2340  int res;
2341  props->superstate = SUPERSTATE_RECALL;
2342  /* move the transfer target to the recall target along with its reference */
2344  res = blond_enter(props);
2346  return res;
2347 }
static int blond_enter(struct attended_transfer_properties *props)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
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 2338 of file bridge_basic.c.

2351 {
2352  switch (stimulus) {
2354  return TRANSFER_FAIL;
2356  return TRANSFER_RESUME;
2357  case STIMULUS_TIMEOUT:
2359  /* It is possible before we hung them up that they queued up a recall target answer
2360  * so we remove it if present as it should not exist.
2361  */
2365  return TRANSFER_RECALLING;
2366  case STIMULUS_NONE:
2374  default:
2375  ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2376  stimulus_strs[stimulus], state_properties[props->state].state_name);
2377  return props->state;
2378  }
2379 }
static void remove_attended_transfer_stimulus(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1148
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2470
#define LOG_WARNING

◆ 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 3527 of file bridge_basic.c.

3529 {
3530  struct bridge_basic_personality *personality = bridge->personality;
3532 
3534 
3535  ao2_cleanup(personality->details[personality->current].pvt);
3536  personality->details[personality->current].pvt = NULL;
3538 
3539  personality->current = type;
3540  if (user_data) {
3541  ao2_ref(user_data, +1);
3542  }
3543  personality->details[personality->current].pvt = user_data;
3544  ast_set_flag(&bridge->feature_flags, personality->details[personality->current].bridge_flags);
3545  if (personality->details[personality->current].on_personality_change) {
3546  personality->details[personality->current].on_personality_change(bridge);
3547  }
3548 }
static void remove_hooks_on_personality_change(struct ast_bridge *bridge)
Remove appropriate hooks when basic bridge personality changes.
Definition: bridge_basic.c:720
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(), and feature_attended_transfer().

◆ bridge_basic_destroy()

static void bridge_basic_destroy ( struct ast_bridge self)
static

Definition at line 703 of file bridge_basic.c.

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

References ao2_cleanup, ast_bridge_base_v_table, and ast_bridge_methods::destroy.

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 3591 of file bridge_basic.c.

3592 {
3593  struct bridge_basic_personality *personality;
3594  int i;
3595 
3596  if (!bridge) {
3597  return NULL;
3598  }
3599 
3600  personality = ao2_alloc(sizeof(*personality), personality_destructor);
3601  if (!personality) {
3602  ao2_ref(bridge, -1);
3603  return NULL;
3604  }
3605  for (i = 0; i < BRIDGE_BASIC_PERSONALITY_END; ++i) {
3606  init_details(&personality->details[i], i);
3607  }
3609  bridge->personality = personality;
3610 
3611  return bridge;
3612 }
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 688 of file bridge_basic.c.

689 {
690  struct bridge_basic_personality *personality = self->personality;
691 
692  ast_assert(personality != NULL);
693 
694  if (personality->details[personality->current].v_table->pull) {
695  personality->details[personality->current].v_table->pull(self, bridge_channel);
696  }
697 
699 
700  ast_bridge_base_v_table.pull(self, bridge_channel);
701 }
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_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 671 of file bridge_basic.c.

672 {
673  struct bridge_basic_personality *personality = self->personality;
674 
675  ast_assert(personality != NULL);
676 
677  if (personality->details[personality->current].v_table->push
678  && personality->details[personality->current].v_table->push(self, bridge_channel, swap)) {
679  return -1;
680  }
681 
682  ast_bridge_channel_update_linkedids(bridge_channel, swap);
683  ast_bridge_channel_update_accountcodes(bridge_channel, swap);
684 
685  return ast_bridge_base_v_table.push(self, bridge_channel, swap);
686 }
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_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 631 of file bridge_basic.c.

632 {
633  int res = 0;
634 
635  res |= setup_bridge_features_builtin(bridge_channel->features, bridge_channel->chan);
636  res |= setup_bridge_features_dynamic(bridge_channel->features, bridge_channel->chan);
637 
638  return res;
639 }
static int setup_bridge_features_dynamic(struct ast_bridge_features *features, struct ast_channel *chan)
Definition: bridge_basic.c:605
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:2384
#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:815

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 1844 of file bridge_basic.c.

1845 {
1846  struct ast_frame hold = {
1847  .frametype = AST_FRAME_CONTROL,
1848  .subclass.integer = AST_CONTROL_HOLD,
1849  };
1850 
1852 }
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_queue_everyone_else(), 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 1897 of file bridge_basic.c.

1898 {
1899  struct ast_bridge_channel **kick_bridge_channels = num_channels ?
1900  ast_alloca(num_channels * sizeof(*kick_bridge_channels)) : NULL;
1901  int i;
1902  int num_bridge_channels = 0;
1903 
1904  ast_bridge_lock_both(dest, src);
1905 
1906  for (i = 0; i < num_channels; ++i) {
1907  struct ast_bridge_channel *kick_bridge_channel;
1908 
1909  kick_bridge_channel = bridge_find_channel(src, kick_channels[i]);
1910  if (!kick_bridge_channel) {
1911  kick_bridge_channel = bridge_find_channel(dest, kick_channels[i]);
1912  }
1913 
1914  /* It's possible (and fine) for the bridge channel to be NULL at this point if the
1915  * channel has hung up already. If that happens, we can just remove it from the list
1916  * of bridge channels to kick from the bridge
1917  */
1918  if (!kick_bridge_channel) {
1919  continue;
1920  }
1921 
1922  kick_bridge_channels[num_bridge_channels++] = kick_bridge_channel;
1923  }
1924 
1925  bridge_do_merge(dest, src, kick_bridge_channels, num_bridge_channels, 0);
1926  ast_bridge_unlock(dest);
1927  ast_bridge_unlock(src);
1928 }
#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 1870 of file bridge_basic.c.

1871 {
1872  struct ast_bridge_channel *bridge_channel;
1873 
1874  ast_bridge_lock_both(src, dest);
1875 
1876  ast_channel_lock(channel);
1877  bridge_channel = ast_channel_get_bridge_channel(channel);
1878  ast_channel_unlock(channel);
1879 
1880  if (bridge_channel) {
1881  ao2_lock(bridge_channel);
1882  bridge_channel->swap = swap;
1883  ao2_unlock(bridge_channel);
1884 
1885  bridge_do_move(dest, bridge_channel, 1, 0);
1886  }
1887 
1888  ast_bridge_unlock(dest);
1889  ast_bridge_unlock(src);
1890 
1891  ao2_cleanup(bridge_channel);
1892 }
#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:10768
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(), 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 2978 of file bridge_basic.c.

2979 {
2980  struct bridge_basic_personality *personality = self->personality;
2981  struct attended_transfer_properties *props = personality->details[personality->current].pvt;
2982 
2983  switch (props->superstate) {
2984  case SUPERSTATE_TRANSFER:
2985  transfer_pull(self, bridge_channel, props);
2986  break;
2987  case SUPERSTATE_RECALL:
2988  recall_pull(self, bridge_channel, props);
2989  break;
2990  }
2991 }
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, 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 2853 of file bridge_basic.c.

2854 {
2855  const char *abort_dtmf;
2856  const char *complete_dtmf;
2857  const char *threeway_dtmf;
2858  const char *swap_dtmf;
2859  struct bridge_basic_personality *personality = self->personality;
2860 
2861  if (!ast_channel_has_role(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME)) {
2862  return 0;
2863  }
2864 
2865  abort_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "abort");
2866  complete_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "complete");
2867  threeway_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "threeway");
2868  swap_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "swap");
2869 
2870  if (!ast_strlen_zero(abort_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2871  abort_dtmf, atxfer_abort, personality->details[personality->current].pvt, NULL,
2873  return -1;
2874  }
2875  if (!ast_strlen_zero(complete_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2876  complete_dtmf, atxfer_complete, personality->details[personality->current].pvt, NULL,
2878  return -1;
2879  }
2880  if (!ast_strlen_zero(threeway_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2881  threeway_dtmf, atxfer_threeway, personality->details[personality->current].pvt, NULL,
2883  return -1;
2884  }
2885  if (!ast_strlen_zero(swap_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2886  swap_dtmf, atxfer_swap, personality->details[personality->current].pvt, NULL,
2888  return -1;
2889  }
2891  personality->details[personality->current].pvt, NULL,
2893  return -1;
2894  }
2895 
2896  return 0;
2897 }
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
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
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
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, 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 662 of file bridge_basic.c.

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

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 1831 of file bridge_basic.c.

1832 {
1833  struct ast_frame ringing = {
1834  .frametype = AST_FRAME_CONTROL,
1835  .subclass.integer = AST_CONTROL_RINGING,
1836  };
1837 
1839 }
@ AST_CONTROL_RINGING

References ast_bridge_queue_everyone_else(), 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 1857 of file bridge_basic.c.

1858 {
1859  struct ast_frame unhold = {
1860  .frametype = AST_FRAME_CONTROL,
1861  .subclass.integer = AST_CONTROL_UNHOLD,
1862  };
1863 
1865 }
static void unhold(struct ast_channel *chan)
Helper method to take a channel in a bridge off hold.
@ AST_CONTROL_UNHOLD

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

◆ 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 {
348  SCOPED_CHANNELLOCK(lock, chan);
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 2100 of file bridge_basic.c.

2101 {
2102  bridge_move(props->target_bridge, props->transferee_bridge, props->transferer, NULL);
2103  return 0;
2104 }
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 2100 of file bridge_basic.c.

2108 {
2109  switch (stimulus) {
2111  play_failsound(props->transferer);
2112  publish_transfer_fail(props);
2113  return TRANSFER_FAIL;
2119  return TRANSFER_CONSULTING;
2121  case STIMULUS_TIMEOUT:
2123  play_failsound(props->transferer);
2124  return TRANSFER_REBRIDGE;
2127  return TRANSFER_THREEWAY;
2129  return TRANSFER_HESITANT;
2130  case STIMULUS_NONE:
2133  default:
2134  ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2135  stimulus_strs[stimulus], state_properties[props->state].state_name);
2136  return props->state;
2137  }
2138 }
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.

◆ clear_stimulus_queue()

static void clear_stimulus_queue ( struct attended_transfer_properties props)
static

Free backlog of stimuli in the queue.

Definition at line 1492 of file bridge_basic.c.

1493 {
1494  struct stimulus_list *list;
1495  SCOPED_AO2LOCK(lock, props);
1496 
1497  while ((list = AST_LIST_REMOVE_HEAD(&props->stimulus_queue, next))) {
1498  ast_free(list);
1499  }
1500 }
#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:602
struct attended_transfer_properties::@343 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 2431 of file bridge_basic.c.

2432 {
2433  ast_callid callid;
2434 
2435  callid = ast_read_threadstorage_callid();
2436  if (callid) {
2437  ast_channel_callid_set(recall, callid);
2438  }
2439 
2440  ast_channel_inherit_variables(transferer, recall);
2441  ast_channel_datastore_inherit(transferer, recall);
2442 
2443  /*
2444  * Stage a snapshot to ensure that a snapshot is always done
2445  * on the recall channel so earlier COLP and CLID setup will
2446  * get published.
2447  */
2451 }
@ AST_CHANNEL_REQUESTOR_REPLACEMENT
Definition: channel.h:1479
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2367
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:6512
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:6849
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:2048

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 2306 of file bridge_basic.c.

2307 {
2308  struct ast_channel *transferee_channel;
2309  struct ast_channel *target_channel;
2310 
2312  &transferee_channel, &target_channel);
2313  bridge_merge(props->transferee_bridge, props->target_bridge, &props->transferer, 1);
2314  play_sound(props->transfer_target, props->xfersound);
2315  publish_transfer_success(props, transferee_channel, target_channel);
2316 
2317  ast_channel_cleanup(transferee_channel);
2318  ast_channel_cleanup(target_channel);
2319  return 0;
2320 }
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 2209 of file bridge_basic.c.

2210 {
2211  return 0;
2212 }

◆ consulting_exit()

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

Definition at line 2209 of file bridge_basic.c.

2216 {
2217  switch (stimulus) {
2219  /* This is a one-of-a-kind event. The transferer and transfer target are talking in
2220  * one bridge, and the transferee has hung up in a separate bridge. In this case, we
2221  * will change the personality of the transfer target bridge back to normal, and play
2222  * a sound to the transferer to indicate the transferee is gone.
2223  */
2225  play_failsound(props->transferer);
2227  /* These next two lines are here to ensure that our reference to the target bridge
2228  * is cleaned up properly and that the target bridge is not destroyed when the
2229  * monitor thread exits
2230  */
2231  ao2_ref(props->target_bridge, -1);
2232  props->target_bridge = NULL;
2233  return TRANSFER_FAIL;
2236  /* We know the transferer is in the target_bridge, so take the other bridge off hold */
2238  return TRANSFER_COMPLETE;
2240  return TRANSFER_REBRIDGE;
2242  play_failsound(props->transferer);
2243  return TRANSFER_REBRIDGE;
2246  return TRANSFER_THREEWAY;
2248  hold(props->transferer);
2249  bridge_move(props->transferee_bridge, props->target_bridge, props->transferer, NULL);
2250  unhold(props->transferer);
2251  return TRANSFER_DOUBLECHECKING;
2252  case STIMULUS_NONE:
2253  case STIMULUS_TIMEOUT:
2257  default:
2258  ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2259  stimulus_strs[stimulus], state_properties[props->state].state_name);
2260  return props->state;
2261  }
2262 }

◆ copy_caller_data()

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

Definition at line 3242 of file bridge_basic.c.

3243 {
3244  ast_channel_lock_both(caller, dest);
3246  ast_channel_inherit_variables(caller, dest);
3247  ast_channel_datastore_inherit(caller, dest);
3248  ast_channel_unlock(dest);
3249  ast_channel_unlock(caller);
3250 }
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8376

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 3253 of file bridge_basic.c.

3254 {
3255  struct ast_channel *chan;
3256  int cause;
3257 
3258  /* Now we request a local channel to prepare to call the destination */
3259  chan = ast_request("Local", ast_channel_nativeformats(caller), NULL, caller, destination,
3260  &cause);
3261  if (!chan) {
3262  return NULL;
3263  }
3264 
3266 
3268 
3269  /* Who is transferring the call. */
3270  pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", ast_channel_name(caller));
3271 
3273 
3274  ast_channel_unlock(chan);
3276 
3277  /* Before we actually dial out let's inherit appropriate information. */
3278  copy_caller_data(chan, caller);
3279 
3280  return chan;
3281 }
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:4337
@ AST_CHANNEL_REQUESTOR_BRIDGE_PEER
Definition: channel.h:1477
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:6432
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
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.
struct ast_party_caller caller
Channel Caller ID information.

References ast_bridge_set_transfer_variables(), ast_channel_lock_both, ast_channel_name(), ast_channel_nativeformats(), ast_channel_req_accountcodes(), AST_CHANNEL_REQUESTOR_BRIDGE_PEER, ast_channel_unlock, ast_request(), ast_channel::caller, 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 2264 of file bridge_basic.c.

2265 {
2266  return 0;
2267 }

◆ 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 2264 of file bridge_basic.c.

2271 {
2272  switch (stimulus) {
2274  play_failsound(props->transferer);
2275  publish_transfer_fail(props);
2276  return TRANSFER_FAIL;
2279  /* We know the transferer is in the transferee, so take the other bridge off hold */
2280  bridge_unhold(props->target_bridge);
2281  return TRANSFER_COMPLETE;
2284  play_failsound(props->transferer);
2285  return TRANSFER_RESUME;
2287  bridge_unhold(props->target_bridge);
2288  return TRANSFER_THREEWAY;
2290  hold(props->transferer);
2291  bridge_move(props->target_bridge, props->transferee_bridge, props->transferer, NULL);
2292  unhold(props->transferer);
2293  return TRANSFER_CONSULTING;
2294  case STIMULUS_NONE:
2295  case STIMULUS_TIMEOUT:
2299  default:
2300  ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2301  stimulus_strs[stimulus], state_properties[props->state].state_name);
2302  return props->state;
2303  }
2304 }

◆ 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:1069
@ AST_FEATURE_REDIRECT
Definition: channel.h:1064
@ AST_FEATURE_PARKCALL
Definition: channel.h:1068
@ AST_FEATURE_AUTOMON
Definition: channel.h:1067
@ AST_FEATURE_DISCONNECT
Definition: channel.h:1065
long int flag
Definition: f2c.h:83
#define ARRAY_LEN(a)
Definition: utils.h:661

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 544 of file bridge_basic.c.

545 {
546  struct dynamic_dtmf_hook_data *hook_data;
547  size_t len_name = strlen(app_name) + 1;
548  size_t len_args = ast_strlen_zero(app_args) ? 0 : strlen(app_args) + 1;
549  size_t len_moh = ast_strlen_zero(moh_class) ? 0 : strlen(moh_class) + 1;
550  size_t len_feature = strlen(feature_name) + 1;
551  size_t len_data = sizeof(*hook_data) + len_name + len_args + len_moh + len_feature;
552  int res;
553 
554  /* Fill in application run hook data. */
555  hook_data = ast_malloc(len_data);
556  if (!hook_data) {
557  return -1;
558  }
559  hook_data->flags = flags;
560  hook_data->app_args_offset = len_args ? len_name : 0;
561  hook_data->moh_offset = len_moh ? len_name + len_args : 0;
562  hook_data->feature_offset = len_name + len_args + len_moh;
563  strcpy(hook_data->app_name, app_name);/* Safe */
564  if (len_args) {
565  strcpy(&hook_data->app_name[hook_data->app_args_offset], app_args);/* Safe */
566  }
567  if (len_moh) {
568  strcpy(&hook_data->app_name[hook_data->moh_offset], moh_class);/* Safe */
569  }
570  strcpy(&hook_data->app_name[hook_data->feature_offset], feature_name);/* Safe */
571 
572  res = ast_bridge_dtmf_hook(features, dtmf, dynamic_dtmf_hook_trip, hook_data,
573  ast_free_ptr,
575  if (res) {
576  ast_free(hook_data);
577  }
578  return res;
579 }
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:476
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 436 of file bridge_basic.c.

438 {
439  struct ast_channel *chan = bridge_channel->chan;
440  const struct dynamic_dtmf_hook_run *run_data = payload;
441 
442  pbx_builtin_setvar_helper(chan, "DYNAMIC_FEATURENAME",
443  &run_data->app_name[run_data->feature_offset]);
444  pbx_builtin_setvar_helper(chan, "DYNAMIC_WHO_ACTIVATED",
445  &run_data->app_name[run_data->activated_offset]);
446 
447  ast_bridge_channel_run_app(bridge_channel, run_data->app_name,
448  run_data->app_args_offset ? &run_data->app_name[run_data->app_args_offset] : NULL,
449  run_data->moh_offset ? &run_data->app_name[run_data->moh_offset] : NULL);
450 }
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 476 of file bridge_basic.c.

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

2726 {
2727  if (props->transferee_bridge) {
2729  props->transferee_bridge = NULL;
2730  }
2731  return 0;
2732 }

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 3293 of file bridge_basic.c.

3294 {
3295  struct ast_bridge_features_attended_transfer *attended_transfer = hook_pvt;
3296  struct attended_transfer_properties *props;
3297  struct ast_bridge *bridge;
3298  char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
3299  char exten[AST_MAX_EXTENSION] = "";
3300  pthread_t thread;
3301 
3302  /* Inhibit the bridge before we do anything else. */
3303  bridge = ast_bridge_channel_merge_inhibit(bridge_channel, +1);
3304 
3305  ast_verb(3, "Channel %s: Started DTMF attended transfer.\n",
3306  ast_channel_name(bridge_channel->chan));
3307 
3308  if (strcmp(bridge->v_table->name, "basic")) {
3309  ast_log(LOG_ERROR, "Channel %s: Attended transfer attempted on unsupported bridge type '%s'.\n",
3310  ast_channel_name(bridge_channel->chan), bridge->v_table->name);
3311  ast_bridge_merge_inhibit(bridge, -1);
3312  ao2_ref(bridge, -1);
3313  return 0;
3314  }
3315 
3316  /* Was the bridge inhibited before we inhibited it? */
3317  if (1 < bridge->inhibit_merge) {
3318  /*
3319  * The peer likely initiated attended transfer at the same time
3320  * and we lost the race.
3321  */
3322  ast_verb(3, "Channel %s: Bridge '%s' does not permit merging at this time.\n",
3323  ast_channel_name(bridge_channel->chan), bridge->uniqueid);
3324  ast_bridge_merge_inhibit(bridge, -1);
3325  ao2_ref(bridge, -1);
3326  return 0;
3327  }
3328 
3329  props = attended_transfer_properties_alloc(bridge_channel->chan,
3330  attended_transfer ? attended_transfer->context : NULL);
3331  if (!props) {
3332  ast_log(LOG_ERROR, "Channel %s: Unable to allocate control structure for performing attended transfer.\n",
3333  ast_channel_name(bridge_channel->chan));
3334  ast_bridge_merge_inhibit(bridge, -1);
3335  ao2_ref(bridge, -1);
3336  return 0;
3337  }
3338 
3339  props->transferee_bridge = bridge;
3340 
3341  if (add_transferer_role(props->transferer, attended_transfer)) {
3342  ast_log(LOG_ERROR, "Channel %s: Unable to set transferrer bridge role.\n",
3343  ast_channel_name(bridge_channel->chan));
3345  return 0;
3346  }
3347 
3348  ast_bridge_channel_write_hold(bridge_channel, NULL);
3349 
3350  /* Grab the extension to transfer to */
3351  if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), props->context)) {
3352  /*
3353  * This is a normal exit for when the user fails
3354  * to specify a valid transfer target. e.g., The user
3355  * hungup, didn't dial any digits, or dialed an invalid
3356  * extension.
3357  */
3358  ast_verb(3, "Channel %s: Unable to acquire target extension for attended transfer.\n",
3359  ast_channel_name(bridge_channel->chan));
3360  ast_bridge_channel_write_unhold(bridge_channel);
3362  return 0;
3363  }
3364 
3365  ast_string_field_set(props, exten, exten);
3366 
3367  /* Fill the variable with the extension and context we want to call */
3368  snprintf(destination, sizeof(destination), "%s@%s", props->exten, props->context);
3369 
3370  ast_debug(1, "Channel %s: Attended transfer target '%s'\n",
3371  ast_channel_name(bridge_channel->chan), destination);
3372 
3373  /* Get a channel that is the destination we wish to call */
3374  props->transfer_target = dial_transfer(bridge_channel->chan, destination);
3375  if (!props->transfer_target) {
3376  ast_log(LOG_ERROR, "Channel %s: Unable to request outbound channel for attended transfer target.\n",
3377  ast_channel_name(bridge_channel->chan));
3378  stream_failsound(props->transferer);
3379  ast_bridge_channel_write_unhold(bridge_channel);
3381  return 0;
3382  }
3383 
3384 
3385  /* Create a bridge to use to talk to the person we are calling */
3387  if (!props->target_bridge) {
3388  ast_log(LOG_ERROR, "Channel %s: Unable to create bridge for attended transfer target.\n",
3389  ast_channel_name(bridge_channel->chan));
3390  stream_failsound(props->transferer);
3391  ast_bridge_channel_write_unhold(bridge_channel);
3392  ast_hangup(props->transfer_target);
3393  props->transfer_target = NULL;
3395  return 0;
3396  }
3398 
3399  if (attach_framehook(props, props->transfer_target)) {
3400  ast_log(LOG_ERROR, "Channel %s: Unable to attach framehook to transfer target.\n",
3401  ast_channel_name(bridge_channel->chan));
3402  stream_failsound(props->transferer);
3403  ast_bridge_channel_write_unhold(bridge_channel);
3404  ast_hangup(props->transfer_target);
3405  props->transfer_target = NULL;
3407  return 0;
3408  }
3409 
3414 
3415  if (ast_call(props->transfer_target, destination, 0)) {
3416  ast_log(LOG_ERROR, "Channel %s: Unable to place outbound call to transfer target.\n",
3417  ast_channel_name(bridge_channel->chan));
3418  stream_failsound(props->transferer);
3419  ast_bridge_channel_write_unhold(bridge_channel);
3420  ast_hangup(props->transfer_target);
3421  props->transfer_target = NULL;
3423  return 0;
3424  }
3425 
3426  /* We increase the refcount of the transfer target because ast_bridge_impart() will
3427  * steal the reference we already have. We need to keep a reference, so the only
3428  * choice is to give it a bump
3429  */
3433  ast_log(LOG_ERROR, "Channel %s: Unable to place transfer target into bridge.\n",
3434  ast_channel_name(bridge_channel->chan));
3435  stream_failsound(props->transferer);
3436  ast_bridge_channel_write_unhold(bridge_channel);
3437  ast_hangup(props->transfer_target);
3438  props->transfer_target = NULL;
3440  return 0;
3441  }
3442 
3444  ast_log(LOG_ERROR, "Channel %s: Unable to create monitoring thread for attended transfer.\n",
3445  ast_channel_name(bridge_channel->chan));
3446  stream_failsound(props->transferer);
3447  ast_bridge_channel_write_unhold(bridge_channel);
3449  return 0;
3450  }
3451 
3452  /* Once the monitoring thread has been created, it is responsible for destroying all
3453  * of the necessary components.
3454  */
3455  return 0;
3456 }
pthread_t thread
Definition: app_meetme.c:1091
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 ast_channel * dial_transfer(struct ast_channel *caller, const char *destination)
Helper function that creates an outgoing channel and returns it immediately.
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
static void stream_failsound(struct ast_channel *chan)
Helper method to stream a fail sound on a channel.
static struct attended_transfer_properties * attended_transfer_properties_alloc(struct ast_channel *transferer, const char *context)
Allocate and initialize attended transfer properties.
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.
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:122
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
Definition: channel.c:6539
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2542
#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:583

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(), exten, 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 3469 of file bridge_basic.c.

3470 {
3471  char xfer_exten[AST_MAX_EXTENSION] = "";
3472  struct ast_bridge_features_blind_transfer *blind_transfer = hook_pvt;
3473  const char *xfer_context;
3474  char *goto_on_blindxfer;
3475 
3476  ast_verb(3, "Channel %s: Started DTMF blind transfer.\n",
3477  ast_channel_name(bridge_channel->chan));
3478 
3479  ast_bridge_channel_write_hold(bridge_channel, NULL);
3480 
3481  ast_channel_lock(bridge_channel->chan);
3482  xfer_context = ast_strdupa(get_transfer_context(bridge_channel->chan,
3483  blind_transfer ? blind_transfer->context : NULL));
3484  goto_on_blindxfer = ast_strdupa(S_OR(pbx_builtin_getvar_helper(bridge_channel->chan,
3485  "GOTO_ON_BLINDXFR"), ""));
3486  ast_channel_unlock(bridge_channel->chan);
3487 
3488  /* Grab the extension to transfer to */
3489  if (grab_transfer(bridge_channel->chan, xfer_exten, sizeof(xfer_exten), xfer_context)) {
3490  ast_bridge_channel_write_unhold(bridge_channel);
3491  return 0;
3492  }
3493 
3494  ast_debug(1, "Channel %s: Blind transfer target '%s@%s'\n",
3495  ast_channel_name(bridge_channel->chan), xfer_exten, xfer_context);
3496 
3497  if (!ast_strlen_zero(goto_on_blindxfer)) {
3498  const char *chan_context;
3499  const char *chan_exten;
3500  int chan_priority;
3501 
3502  ast_debug(1, "Channel %s: After transfer, transferrer goes to %s\n",
3503  ast_channel_name(bridge_channel->chan), goto_on_blindxfer);
3504 
3505  ast_channel_lock(bridge_channel->chan);
3506  chan_context = ast_strdupa(ast_channel_context(bridge_channel->chan));
3507  chan_exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
3508  chan_priority = ast_channel_priority(bridge_channel->chan);
3509  ast_channel_unlock(bridge_channel->chan);
3510  ast_bridge_set_after_go_on(bridge_channel->chan,
3511  chan_context, chan_exten, chan_priority, goto_on_blindxfer);
3512  }
3513 
3514  if (ast_bridge_transfer_blind(0, bridge_channel->chan, xfer_exten, xfer_context,
3516  && !ast_strlen_zero(goto_on_blindxfer)) {
3517  ast_bridge_discard_after_goto(bridge_channel->chan);
3518  }
3519 
3520  return 0;
3521 }
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:4410
@ 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)
const char * ast_channel_context(const struct ast_channel *chan)
int ast_channel_priority(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.

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 1380 of file bridge_basic.c.

1381 {
1382  if (!ast_strlen_zero(context)) {
1383  return context;
1384  }
1385  context = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
1386  if (!ast_strlen_zero(context)) {
1387  return context;
1388  }
1389  context = ast_channel_macrocontext(transferer);
1390  if (!ast_strlen_zero(context)) {
1391  return context;
1392  }
1393  context = ast_channel_context(transferer);
1394  if (!ast_strlen_zero(context)) {
1395  return context;
1396  }
1397  return "default";
1398 }
const char * ast_channel_macrocontext(const struct ast_channel *chan)

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

Referenced by attended_transfer_properties_alloc().

◆ 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 1618 of file bridge_basic.c.

1621 {
1622  struct ast_bridge *transferer_bridge;
1623 
1624  ast_channel_lock(transferer);
1625  transferer_bridge = ast_channel_get_bridge(transferer);
1626  ast_channel_unlock(transferer);
1627 
1628  if (transferer_bridge == transferee_bridge) {
1629  get_transfer_parties_transferer_bridge(transferee_bridge, target_bridge,
1630  transferer, transferee, transfer_target);
1631  } else if (transferer_bridge == target_bridge) {
1632  get_transfer_parties_transferer_bridge(target_bridge, transferee_bridge,
1633  transferer, transfer_target, transferee);
1634  } else {
1635  get_transfer_party_non_transferer_bridge(transferee_bridge, transferee);
1636  get_transfer_party_non_transferer_bridge(target_bridge, transfer_target);
1637  }
1638 
1639  ao2_cleanup(transferer_bridge);
1640 }
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:10720

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 1593 of file bridge_basic.c.

1596 {
1597  *transferer_peer = ast_bridge_peer(transferer_bridge, transferer);
1598  get_transfer_party_non_transferer_bridge(other_bridge, other_party);
1599 }
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 1573 of file bridge_basic.c.

1575 {
1576  if (bridge && bridge->num_channels == 1) {
1577  *party = ast_channel_ref(AST_LIST_FIRST(&bridge->channels)->chan);
1578  } else {
1579  *party = NULL;
1580  }
1581 }
#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 3158 of file bridge_basic.c.

3159 {
3160  int res;
3161  int digit_timeout;
3162  int attempts = 0;
3163  int max_attempts;
3164  struct ast_features_xfer_config *xfer_cfg;
3165  char *retry_sound;
3166  char *invalid_sound;
3167 
3168  ast_channel_lock(chan);
3169  xfer_cfg = ast_get_chan_features_xfer_config(chan);
3170  if (!xfer_cfg) {
3171  ast_log(LOG_ERROR, "Channel %s: Unable to get transfer configuration\n",
3172  ast_channel_name(chan));
3173  ast_channel_unlock(chan);
3174  return -1;
3175  }
3176  digit_timeout = xfer_cfg->transferdigittimeout * 1000;
3177  max_attempts = xfer_cfg->transferdialattempts;
3178  retry_sound = ast_strdupa(xfer_cfg->transferretrysound);
3179  invalid_sound = ast_strdupa(xfer_cfg->transferinvalidsound);
3180  ao2_ref(xfer_cfg, -1);
3181  ast_channel_unlock(chan);
3182 
3183  /* Play the simple "transfer" prompt out and wait */
3184  res = ast_stream_and_wait(chan, "pbx-transfer", AST_DIGIT_ANY);
3185  ast_stopstream(chan);
3186  if (res < 0) {
3187  /* Hangup or error */
3188  return -1;
3189  }
3190  if (res) {
3191  /* Store the DTMF digit that interrupted playback of the file. */
3192  exten[0] = res;
3193  }
3194 
3195  /* Drop to dialtone so they can enter the extension they want to transfer to */
3196  do {
3197  ++attempts;
3198 
3199  ast_test_suite_event_notify("TRANSFER_BEGIN_DIAL",
3200  "Channel: %s\r\n"
3201  "Attempt: %d",
3202  ast_channel_name(chan), attempts);
3203  res = ast_app_dtget(chan, context, exten, exten_len, exten_len - 1, digit_timeout);
3204  ast_test_suite_event_notify("TRANSFER_DIALLED",
3205  "Channel: %s\r\n"
3206  "Attempt: %d\r\n"
3207  "Dialled: %s\r\n"
3208  "Result: %s",
3209  ast_channel_name(chan), attempts, exten, res > 0 ? "Success" : "Failure");
3210  if (res < 0) {
3211  /* Hangup or error */
3212  res = -1;
3213  } else if (!res) {
3214  /* 0 for invalid extension dialed. */
3215  if (ast_strlen_zero(exten)) {
3216  ast_verb(3, "Channel %s: Dialed no digits.\n", ast_channel_name(chan));
3217  } else {
3218  ast_verb(3, "Channel %s: Dialed '%s@%s' does not exist.\n",
3219  ast_channel_name(chan), exten, context);
3220  }
3221  if (attempts < max_attempts) {
3222  ast_stream_and_wait(chan, retry_sound, AST_DIGIT_NONE);
3223  } else {
3224  ast_stream_and_wait(chan, invalid_sound, AST_DIGIT_NONE);
3225  }
3226  memset(exten, 0, exten_len);
3227  res = 1;
3228  } else {
3229  /* Dialed extension is valid. */
3230  res = 0;
3231  }
3232  } while (res > 0 && attempts < max_attempts);
3233 
3234  ast_test_suite_event_notify("TRANSFER_DIAL_FINAL",
3235  "Channel: %s\r\n"
3236  "Result: %s",
3237  ast_channel_name(chan), res == 0 ? "Success" : "Failure");
3238 
3239  return res ? -1 : 0;
3240 }
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:1855
#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
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:189

References ao2_ref, ast_app_dtget(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, AST_DIGIT_ANY, AST_DIGIT_NONE, 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, context, exten, LOG_ERROR, 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().

◆ 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 2140 of file bridge_basic.c.

2149 {
2150  switch (stimulus) {
2152  play_failsound(props->transferer);
2153  publish_transfer_fail(props);
2154  return TRANSFER_FAIL;
2159  return TRANSFER_DOUBLECHECKING;
2161  case STIMULUS_TIMEOUT:
2163  play_failsound(props->transferer);
2164  return TRANSFER_RESUME;
2166  return TRANSFER_THREEWAY;
2168  hold(props->transferer);
2169  return TRANSFER_CALLING_TARGET;
2170  case STIMULUS_NONE:
2173  default:
2174  ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2175  stimulus_strs[stimulus], state_properties[props->state].state_name);
2176  return props->state;
2177  }
2178 }

◆ hold()

static void hold ( struct ast_channel chan)
static

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

Definition at line 1772 of file bridge_basic.c.

1773 {
1774  struct ast_bridge_channel *bridge_channel;
1775 
1776  if (!chan) {
1777  return;
1778  }
1779 
1781  bridge_channel = ast_channel_get_bridge_channel(chan);
1783 
1784  if (bridge_channel) {
1785  ast_bridge_channel_write_hold(bridge_channel, NULL);
1786  ao2_ref(bridge_channel, -1);
1787  }
1788 }

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(), sip_peer_hold(), and sla_hold_str().

◆ init_details()

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

Definition at line 3572 of file bridge_basic.c.

3574 {
3575  switch (type) {
3577  details->v_table = &personality_normal_v_table;
3578  details->bridge_flags = NORMAL_FLAGS;
3580  break;
3582  details->v_table = &personality_atxfer_v_table;
3583  details->bridge_flags = TRANSFER_FLAGS;
3584  break;
3585  default:
3586  ast_log(LOG_WARNING, "Asked to initialize unexpected basic bridge personality type.\n");
3587  break;
3588  }
3589 }
#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 3560 of file bridge_basic.c.

3561 {
3562  struct ast_bridge_channel *iter;
3563 
3565  if (add_normal_hooks(bridge, iter)) {
3566  ast_log(LOG_WARNING, "Unable to set up bridge hooks for channel %s. Features may not work properly\n",
3567  ast_channel_name(iter->chan));
3568  }
3569  }
3570 }

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 3550 of file bridge_basic.c.

3551 {
3552  struct bridge_basic_personality *personality = obj;
3553  int i;
3554 
3555  for (i = 0; i < BRIDGE_BASIC_PERSONALITY_END; ++i) {
3556  ao2_cleanup(personality->details[i].pvt);
3557  }
3558 }

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 1736 of file bridge_basic.c.

1737 {
1738  char *sound;
1739 
1740  ast_channel_lock(chan);
1742  ast_channel_unlock(chan);
1743 
1744  if (sound) {
1745  play_sound(chan, sound);
1746  ast_free(sound);
1747  }
1748 }
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().

◆ 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 1717 of file bridge_basic.c.

1718 {
1719  struct ast_bridge_channel *bridge_channel;
1720 
1722  bridge_channel = ast_channel_get_bridge_channel(chan);
1724 
1725  if (bridge_channel) {
1726  ast_bridge_channel_queue_playfile(bridge_channel, NULL, sound, NULL);
1727  ao2_ref(bridge_channel, -1);
1728  }
1729 }
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 1692 of file bridge_basic.c.

1693 {
1694  struct ast_attended_transfer_message *transfer_msg;
1695 
1696  transfer_msg = ast_attended_transfer_message_create(0, props->transferer,
1697  props->transferee_bridge, props->transferer, props->target_bridge,
1698  NULL, NULL);
1699 
1700  if (!transfer_msg) {
1701  ast_log(LOG_ERROR, "Unable to publish failed transfer from %s\n",
1702  ast_channel_name(props->transferer));
1703  return;
1704  }
1705 
1706  transfer_msg->result = AST_BRIDGE_TRANSFER_FAIL;
1708  ao2_cleanup(transfer_msg);
1709 }
@ 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.

◆ 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 1645 of file bridge_basic.c.

1647 {
1648  struct ast_attended_transfer_message *transfer_msg;
1649 
1650  transfer_msg = ast_attended_transfer_message_create(0, props->transferer,
1651  props->transferee_bridge, props->transferer, props->target_bridge,
1652  transferee_channel, target_channel);
1653 
1654  if (!transfer_msg) {
1655  ast_log(LOG_ERROR, "Unable to publish successful attended transfer from %s\n",
1656  ast_channel_name(props->transferer));
1657  return;
1658  }
1659 
1662  ao2_cleanup(transfer_msg);
1663 }
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 1668 of file bridge_basic.c.

1670 {
1671  struct ast_attended_transfer_message *transfer_msg;
1672 
1673  transfer_msg = ast_attended_transfer_message_create(0, props->transferer,
1674  props->transferee_bridge, props->transferer, props->target_bridge,
1675  transferee_channel, target_channel);
1676 
1677  if (!transfer_msg) {
1678  ast_log(LOG_ERROR, "Unable to publish successful three-way transfer from %s\n",
1679  ast_channel_name(props->transferer));
1680  return;
1681  }
1682 
1684  props->transferee_bridge);
1686  ao2_cleanup(transfer_msg);
1687 }
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 2388 of file bridge_basic.c.

2389 {
2391 
2392  switch (ast_dial_state(dial)) {
2393  default:
2399  /* Failure cases */
2401  break;
2406  /* Don't care about these cases */
2407  break;
2409  /* We struck gold! */
2412  break;
2413  }
2414 }
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
Return state of dial.
Definition: dial.c:1012
@ 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
void * ast_dial_get_user_data(struct ast_dial *dial)
Return the user data on a dial structure.
Definition: dial.c:1274
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition: dial.c:993

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 2937 of file bridge_basic.c.

2938 {
2939  if (self == props->target_bridge) {
2940  /* Once we're in the recall superstate, we no longer care about this bridge */
2941  return;
2942  }
2943 
2944  if (bridge_channel->chan == props->recall_target) {
2946  return;
2947  }
2948 
2949  if (self->num_channels == 0) {
2950  /* Empty bridge means all transferees are gone for sure */
2952  return;
2953  }
2954 
2955  if (self->num_channels == 1) {
2956  struct ast_bridge_channel *target_bridge_channel;
2957 
2958  if (!props->recall_target) {
2959  /* No recall target means that the pull happened on a transferee. If there's still
2960  * a channel left in the bridge, we don't need to send a stimulus
2961  */
2962  return;
2963  }
2964 
2966  target_bridge_channel = ast_channel_get_bridge_channel(props->recall_target);
2968 
2969  if (target_bridge_channel) {
2970  if (AST_LIST_FIRST(&self->channels) == target_bridge_channel) {
2972  }
2973  ao2_ref(target_bridge_channel, -1);
2974  }
2975  }
2976 }

References ao2_ref, ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, AST_LIST_FIRST, ast_bridge_channel::chan, 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 2453 of file bridge_basic.c.

2454 {
2456  struct ast_channel *recall;
2457 
2458  if (!cap) {
2459  return -1;
2460  }
2461 
2463 
2464  /* When we dial the transfer target, since we are communicating
2465  * with a local channel, we can place the local channel in a bridge
2466  * and then call out to it. When recalling the transferer, though, we
2467  * have to use the dialing API because the channel is not local.
2468  */
2469  props->dial = ast_dial_create();
2470  if (!props->dial) {
2471  return -1;
2472  }
2473 
2474  if (ast_dial_append(props->dial, props->transferer_type, props->transferer_addr, NULL)) {
2475  return -1;
2476  }
2477 
2478  if (ast_dial_prerun(props->dial, NULL, cap)) {
2479  return -1;
2480  }
2481 
2482  /*
2483  * Setup callid, variables, datastores, accountcode, peeraccount,
2484  * COLP, and CLID on the recalled transferrer.
2485  */
2486  recall = ast_dial_get_channel(props->dial, 0);
2487  if (!recall) {
2488  return -1;
2489  }
2490  ast_channel_lock_both(recall, props->transferer);
2491 
2493  ast_channel_caller(props->transferer));
2495  &props->original_transferer_colp);
2496 
2497  common_recall_channel_setup(recall, props->transferer);
2498  ast_channel_unlock(recall);
2500 
2502 
2503  ao2_ref(props, +1);
2504  ast_dial_set_user_data(props->dial, props);
2505 
2506  if (ast_dial_run(props->dial, NULL, 1) == AST_DIAL_RESULT_FAILED) {
2507  ao2_ref(props, -1);
2508  return -1;
2509  }
2510 
2512  return 0;
2513 }
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:1980
void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
Set a callback for state changes.
Definition: dial.c:1264
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:282
void ast_dial_set_user_data(struct ast_dial *dial, void *user_data)
Set user data on a dial structure.
Definition: dial.c:1269
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:433
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:1253
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:939
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:225
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
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
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:936

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 2453 of file bridge_basic.c.

2517 {
2518  /* No matter what the outcome was, we need to kill off the dial */
2519  ast_dial_join(props->dial);
2520  ast_dial_destroy(props->dial);
2521  props->dial = NULL;
2522  /* This reference is the one we incremented for the dial state callback (recall_callback) to use */
2523  ao2_ref(props, -1);
2524 
2525  switch (stimulus) {
2527  return TRANSFER_FAIL;
2528  case STIMULUS_TIMEOUT:
2530  ++props->retry_attempts;
2531  if (props->retry_attempts >= props->atxfercallbackretries) {
2532  return TRANSFER_FAIL;
2533  }
2534  if (props->atxferloopdelay) {
2536  }
2537  return TRANSFER_RETRANSFER;
2539  /* Setting this datastore up will allow the transferer to have all of his
2540  * call features set up automatically when the bridge changes back to a
2541  * normal personality
2542  */
2547  ast_hangup(props->recall_target);
2549  return TRANSFER_FAIL;
2550  }
2551  return TRANSFER_RESUME;
2552  case STIMULUS_NONE:
2560  default:
2561  ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2562  stimulus_strs[stimulus], state_properties[props->state].state_name);
2563  return props->state;
2564  }
2565 }
enum ast_dial_result ast_dial_join(struct ast_dial *dial)
Cancel async thread.
Definition: dial.c:1021
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1086

◆ remove_attended_transfer_stimulus()

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

Definition at line 1550 of file bridge_basic.c.

1552 {
1553  struct stimulus_list *list;
1554 
1555  ao2_lock(props);
1557  if (list->stimulus == stimulus) {
1559  ast_free(list);
1560  break;
1561  }
1562  }
1564  ao2_unlock(props);
1565 }
#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.

◆ 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 720 of file bridge_basic.c.

721 {
722  struct ast_bridge_channel *iter;
723 
727  }
728 }
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 2187 of file bridge_basic.c.

2188 {
2189  return 0;
2190 }

◆ retransfer_enter()

static int retransfer_enter ( struct attended_transfer_properties props)
static

Definition at line 2601 of file bridge_basic.c.

2602 {
2604  char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
2605  int cause;
2606 
2607  if (!cap) {
2608  return -1;
2609  }
2610 
2611  snprintf(destination, sizeof(destination), "%s@%s", props->exten, props->context);
2612 
2614 
2615  /* Get a channel that is the destination we wish to call */
2616  props->recall_target = ast_request("Local", cap, NULL, NULL, destination, &cause);
2617  if (!props->recall_target) {
2618  ast_log(LOG_ERROR, "Unable to request outbound channel for recall target\n");
2619  return -1;
2620  }
2621 
2622