Asterisk - The Open Source Telephony Project  GIT-master-44aef04
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"

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

◆ TRANSFER_FLAGS

#define TRANSFER_FLAGS   AST_BRIDGE_FLAG_SMART

Definition at line 54 of file bridge_basic.c.

Referenced by init_details().

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 atxferdroppcall 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 atxferdroppcall 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 atxferdroppcall 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 atxferdroppcall 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 };
Rebridge state.
Definition: bridge_basic.c:870
Resume state.
Definition: bridge_basic.c:903
Complete state.
Wait to Retransfer state.
Fail state.
Consulting state.
Definition: bridge_basic.c:957
Retransfer state.
Double-checking state.
Definition: bridge_basic.c:987
Calling Target state.
Definition: bridge_basic.c:808
Wait to recall state.
Blond non-final state.
Recalling state.
Hesitant state.
Definition: bridge_basic.c:842
Blond state.
Threeway state.
Definition: bridge_basic.c:929

◆ 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 };

◆ 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 };

◆ 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 };
Recall superstate.
Definition: bridge_basic.c:768
Transfer superstate.
Definition: bridge_basic.c:753

◆ 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 };

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.

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

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
struct ast_bridge_features * features
#define NULL
Definition: resample.c:96
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:3328
static int bridge_basic_setup_features(struct ast_bridge_channel *bridge_channel)
Definition: bridge_basic.c:631

◆ add_transferer_role()

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

Definition at line 3121 of file bridge_basic.c.

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

3122 {
3123  const char *atxfer_abort;
3124  const char *atxfer_threeway;
3125  const char *atxfer_complete;
3126  const char *atxfer_swap;
3127  struct ast_features_xfer_config *xfer_cfg;
3128  SCOPED_CHANNELLOCK(lock, chan);
3129 
3130  xfer_cfg = ast_get_chan_features_xfer_config(chan);
3131  if (!xfer_cfg) {
3132  return -1;
3133  }
3134  if (attended_transfer) {
3135  atxfer_abort = ast_strdupa(S_OR(attended_transfer->abort, xfer_cfg->atxferabort));
3136  atxfer_threeway = ast_strdupa(S_OR(attended_transfer->threeway, xfer_cfg->atxferthreeway));
3137  atxfer_complete = ast_strdupa(S_OR(attended_transfer->complete, xfer_cfg->atxfercomplete));
3138  atxfer_swap = ast_strdupa(S_OR(attended_transfer->swap, xfer_cfg->atxferswap));
3139  } else {
3140  atxfer_abort = ast_strdupa(xfer_cfg->atxferabort);
3141  atxfer_threeway = ast_strdupa(xfer_cfg->atxferthreeway);
3142  atxfer_complete = ast_strdupa(xfer_cfg->atxfercomplete);
3143  atxfer_swap = ast_strdupa(xfer_cfg->atxferswap);
3144  }
3145  ao2_ref(xfer_cfg, -1);
3146 
3148  ast_channel_set_bridge_role_option(chan, AST_TRANSFERER_ROLE_NAME, "abort", atxfer_abort) ||
3149  ast_channel_set_bridge_role_option(chan, AST_TRANSFERER_ROLE_NAME, "complete", atxfer_complete) ||
3150  ast_channel_set_bridge_role_option(chan, AST_TRANSFERER_ROLE_NAME, "threeway", atxfer_threeway) ||
3152 }
Feature configuration relating to transfers.
char complete[MAXIMUM_DTMF_FEATURE_STRING]
struct ast_features_xfer_config * ast_get_chan_features_xfer_config(struct ast_channel *chan)
Get the transfer configuration options for a channel.
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:317
static int atxfer_complete(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses complete sequence.
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:379
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int atxfer_threeway(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses threeway sequence.
static int atxfer_abort(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses abort sequence.
#define AST_TRANSFERER_ROLE_NAME
Definition: bridge_basic.h:36
char threeway[MAXIMUM_DTMF_FEATURE_STRING]
static int atxfer_swap(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses swap sequence.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
char abort[MAXIMUM_DTMF_FEATURE_STRING]
char swap[MAXIMUM_DTMF_FEATURE_STRING]

◆ ast_bridge_basic_new()

struct ast_bridge* ast_bridge_basic_new ( void  )

Create a new basic class bridge.

Return values
apointer to a new bridge on success
NULLon failure

Example usage:

struct ast_bridge *bridge;

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

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

3618 {
3619  struct ast_bridge *bridge;
3620 
3621  bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table);
3622  bridge = bridge_base_init(bridge,
3625  bridge = bridge_basic_personality_alloc(bridge);
3626  bridge = bridge_register(bridge);
3627  return bridge;
3628 }
struct ast_bridge * bridge_register(struct ast_bridge *bridge)
Register the new bridge with the system.
Definition: bridge.c:709
#define NULL
Definition: resample.c:96
#define NORMAL_FLAGS
Definition: bridge_basic.c:51
struct ast_bridge * bridge_alloc(size_t size, const struct ast_bridge_methods *v_table)
Definition: bridge.c:724
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:760
static struct ast_bridge * bridge_basic_personality_alloc(struct ast_bridge *bridge)
Structure that contains information about a bridge.
Definition: bridge.h:357
struct ast_bridge_methods ast_bridge_basic_v_table
Bridge basic class virtual method table.

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

Flags to set on the bridge. These are added to the flags already set.

Definition at line 3630 of file bridge_basic.c.

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

3631 {
3633  struct bridge_basic_personality *personality = bridge->personality;
3634 
3635  personality->details[personality->current].bridge_flags |= flags;
3636  ast_set_flag(&bridge->feature_flags, flags);
3637 }
struct ast_flags feature_flags
Definition: bridge.h:377
unsigned int bridge_flags
Definition: bridge_basic.c:317
#define ast_set_flag(p, flag)
Definition: utils.h:70
enum bridge_basic_personality_type current
Definition: bridge_basic.c:329
void * personality
Definition: bridge.h:361
ast_mutex_t lock
Definition: app_meetme.c:1091
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
structure that organizes different personalities for basic bridges.
Definition: bridge_basic.c:327
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:493
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:480
struct personality_details details[BRIDGE_BASIC_PERSONALITY_END]
Definition: bridge_basic.c:331

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

References bridge_features_ds_set_full().

Referenced by pre_bridge_setup().

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

◆ 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.
Return values
flagson success.
NULLif the datastore does not exist.

Definition at line 268 of file bridge_basic.c.

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

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

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
Structure for a data store object.
Definition: datastore.h:68
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:2390
#define NULL
Definition: resample.c:96
void * data
Definition: datastore.h:70

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

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

Referenced by func_channel_read().

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 }
#define ast_channel_lock(chan)
Definition: channel.h:2902
static int dtmf_features_flags_to_string(struct ast_flags *feature_flags, char *buffer, size_t buffer_size)
Definition: bridge_basic.c:133
struct ast_flags * ast_bridge_features_ds_get(struct ast_channel *chan)
Get DTMF feature flags from the channel.
Definition: bridge_basic.c:268
#define ast_channel_unlock(chan)
Definition: channel.h:2903
Structure used to handle boolean flags.
Definition: utils.h:199

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

References bridge_features_ds_set_full().

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

259 {
260  return bridge_features_ds_set_full(chan, flags, 1);
261 }
static int bridge_features_ds_set_full(struct ast_channel *chan, struct ast_flags *flags, int replace)
Definition: bridge_basic.c:224

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

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

Referenced by func_channel_write_real().

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_channel_lock(chan)
Definition: channel.h:2902
unsigned int flags
Definition: utils.h:200
static int build_dtmf_features(struct ast_flags *flags, const char *features)
Definition: bridge_basic.c:162
#define ast_log
Definition: astobj2.c:42
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
#define LOG_ERROR
Definition: logger.h:285
#define ast_channel_unlock(chan)
Definition: channel.h:2903
Structure used to handle boolean flags.
Definition: utils.h:199
const char * ast_channel_name(const struct ast_channel *chan)

◆ ast_bridging_init_basic()

void ast_bridging_init_basic ( void  )

Initialize the basic bridge class for use by the system.

Definition at line 3639 of file bridge_basic.c.

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

3640 {
3641  /* Setup bridge basic subclass v_table. */
3643  ast_bridge_basic_v_table.name = "basic";
3647 
3648  /*
3649  * Personality vtables don't have the same rules as
3650  * normal bridge vtables. These vtable functions are
3651  * used as alterations to the ast_bridge_basic_v_table
3652  * method functionality and are checked for NULL before
3653  * calling.
3654  */
3655  personality_normal_v_table.name = "normal";
3657 
3658  personality_atxfer_v_table.name = "attended transfer";
3661 
3664 }
static void bridge_basic_destroy(struct ast_bridge *self)
Definition: bridge_basic.c:703
struct ast_bridge_methods personality_normal_v_table
struct ast_bridge_methods personality_atxfer_v_table
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
const char * name
Definition: bridge.h:267
#define NULL
Definition: resample.c:96
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
static int bridge_personality_atxfer_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
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:3123
struct ast_bridge_methods ast_bridge_basic_v_table
Bridge basic class virtual method table.
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 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
ast_bridge_pull_channel_fn pull
Definition: bridge.h:275
ast_bridge_destructor_fn destroy
Definition: bridge.h:269
ast_bridge_push_channel_fn push
Definition: bridge.h:273
static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Internal built in feature for attended transfers.
static void bridge_personality_atxfer_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)

◆ attach_framehook()

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

Definition at line 3098 of file bridge_basic.c.

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(), retransfer_enter(), and wait_to_retransfer_exit().

3099 {
3100  struct ast_framehook_interface target_interface = {
3102  .event_cb = transfer_target_framehook_cb,
3104  .consume_cb = transfer_target_framehook_consume,
3105  .disable_inheritance = 1,
3106  };
3107 
3108  ao2_ref(props, +1);
3109  target_interface.data = props;
3110 
3111  ast_channel_lock(channel);
3112  props->target_framehook_id = ast_framehook_attach(channel, &target_interface);
3113  ast_channel_unlock(channel);
3114  if (props->target_framehook_id == -1) {
3115  ao2_ref(props, -1);
3116  return -1;
3117  }
3118  return 0;
3119 }
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...
#define ast_channel_lock(chan)
Definition: channel.h:2902
static void transfer_target_framehook_destroy_cb(void *data)
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 ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ast_frame * transfer_target_framehook_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
Frame hook for transfer target channel.
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
#define ast_channel_unlock(chan)
Definition: channel.h:2903

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

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, stimulus_strs, TRANSFER_STATE_FLAG_TERMINAL, attended_transfer_properties::transferer, and wait_for_stimulus().

Referenced by feature_attended_transfer().

3045 {
3046  struct attended_transfer_properties *props = data;
3047  ast_callid callid;
3048 
3049  /*
3050  * Set thread callid to the transferer's callid because we
3051  * are doing all this on that channel's behalf.
3052  */
3053  ast_channel_lock(props->transferer);
3054  callid = ast_channel_callid(props->transferer);
3056  if (callid) {
3058  }
3059 
3060  for (;;) {
3061  enum attended_transfer_stimulus stimulus;
3062 
3063  ast_debug(1, "About to enter state %s for attended transfer %p\n", state_properties[props->state].state_name, props);
3064 
3065  if (state_properties[props->state].enter &&
3066  state_properties[props->state].enter(props)) {
3067  ast_log(LOG_ERROR, "State %s enter function returned an error for attended transfer %p\n",
3068  state_properties[props->state].state_name, props);
3069  break;
3070  }
3071 
3073  ast_debug(1, "State %s is a terminal state. Ending attended transfer %p\n",
3074  state_properties[props->state].state_name, props);
3075  break;
3076  }
3077 
3078  stimulus = wait_for_stimulus(props);
3079 
3080  ast_debug(1, "Received stimulus %s on attended transfer %p\n", stimulus_strs[stimulus], props);
3081 
3083 
3084  props->state = state_properties[props->state].exit(props, stimulus);
3085 
3086  ast_debug(1, "Told to enter state %s exit on attended transfer %p\n", state_properties[props->state].state_name, props);
3087  }
3088 
3090 
3091  if (callid) {
3093  }
3094 
3095  return NULL;
3096 }
enum attended_transfer_state(* exit)(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
#define ast_channel_lock(chan)
Definition: channel.h:2902
static void attended_transfer_properties_shutdown(struct attended_transfer_properties *props)
Initiate shutdown of attended transfer properties.
static const struct attended_transfer_state_properties state_properties[]
const char * stimulus_strs[]
String representations of the various stimuli.
unsigned int ast_callid
Definition: logger.h:87
#define ast_assert(a)
Definition: utils.h:650
#define NULL
Definition: resample.c:96
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
Definition: logger.c:1990
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:1971
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
enum attended_transfer_state state
#define LOG_ERROR
Definition: logger.h:285
int(* enter)(struct attended_transfer_properties *props)
attended_transfer_stimulus
Stimuli that can cause transfer state changes.
#define ast_channel_unlock(chan)
Definition: channel.h:2903
enum attended_transfer_state_flags flags
struct ast_channel * transferer
ast_callid ast_channel_callid(const struct ast_channel *chan)
static enum attended_transfer_stimulus wait_for_stimulus(struct attended_transfer_properties *props)
Collection of data related to an attended transfer attempt.

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

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

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 ast_channel_lock(chan)
Definition: channel.h:2902
Feature configuration relating to transfers.
struct ast_flags * ast_bridge_features_ds_get(struct ast_channel *chan)
Get DTMF feature flags from the channel.
Definition: bridge_basic.c:268
struct ast_features_xfer_config * ast_get_chan_features_xfer_config(struct ast_channel *chan)
Get the transfer configuration options for a channel.
static const char * get_transfer_context(struct ast_channel *transferer, const char *context)
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct ast_flags transferer_features
#define LOG_ERROR
Definition: logger.h:285
static void attended_transfer_properties_destructor(void *obj)
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ast_channel_unlock(chan)
Definition: channel.h:2903
Structure used to handle boolean flags.
Definition: utils.h:199
struct ast_party_connected_line original_transferer_colp
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:2017
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2927
const char * ast_channel_name(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_channel * transferer
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
Collection of data related to an attended transfer attempt.

◆ attended_transfer_properties_destructor()

static void attended_transfer_properties_destructor ( void *  obj)
static

Definition at line 1353 of file bridge_basic.c.

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

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 }
struct ast_bridge * transferee_bridge
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2058
struct ast_channel * transfer_target
struct ast_channel * recall_target
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2949
struct ast_bridge * target_bridge
#define ast_cond_destroy(cond)
Definition: lock.h:200
struct ast_party_connected_line original_transferer_colp
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_channel * transferer
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
Collection of data related to an attended transfer attempt.

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

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

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 }
static void clear_stimulus_queue(struct attended_transfer_properties *props)
Free backlog of stimuli in the queue.
static void bridge_basic_change_personality(struct ast_bridge *bridge, enum bridge_basic_personality_type type, void *user_data)
Change basic bridge personality.
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:336
struct ast_bridge * transferee_bridge
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
void ast_bridge_merge_inhibit(struct ast_bridge *bridge, int request)
Adjust the bridge merge inhibit request count.
Definition: bridge.c:3061
struct ast_bridge * target_bridge
#define AST_TRANSFERER_ROLE_NAME
Definition: bridge_basic.h:36
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_channel * transferer

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

References ast_debug, stimulate_attended_transfer(), and STIMULUS_DTMF_ATXFER_ABORT.

Referenced by add_transferer_role(), and bridge_personality_atxfer_push().

2742 {
2743  struct attended_transfer_properties *props = hook_pvt;
2744 
2745  ast_debug(1, "Transferer on attended transfer %p pressed abort sequence\n", props);
2747  return 0;
2748 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static void stimulate_attended_transfer(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
Collection of data related to an attended transfer attempt.

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

References ast_debug, stimulate_attended_transfer(), and STIMULUS_DTMF_ATXFER_COMPLETE.

Referenced by add_transferer_role(), and bridge_personality_atxfer_push().

2756 {
2757  struct attended_transfer_properties *props = hook_pvt;
2758 
2759  ast_debug(1, "Transferer on attended transfer %p pressed complete sequence\n", props);
2761  return 0;
2762 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static void stimulate_attended_transfer(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
Collection of data related to an attended transfer attempt.

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

References ast_debug, stimulate_attended_transfer(), and STIMULUS_DTMF_ATXFER_SWAP.

Referenced by add_transferer_role(), and bridge_personality_atxfer_push().

2784 {
2785  struct attended_transfer_properties *props = hook_pvt;
2786 
2787  ast_debug(1, "Transferer on attended transfer %p pressed swap sequence\n", props);
2789  return 0;
2790 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static void stimulate_attended_transfer(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
Collection of data related to an attended transfer attempt.

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

References ast_debug, stimulate_attended_transfer(), and STIMULUS_DTMF_ATXFER_THREEWAY.

Referenced by add_transferer_role(), and bridge_personality_atxfer_push().

2770 {
2771  struct attended_transfer_properties *props = hook_pvt;
2772 
2773  ast_debug(1, "Transferer on attended transfer %p pressed threeway sequence\n", props);
2775  return 0;
2776 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static void stimulate_attended_transfer(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
Collection of data related to an attended transfer attempt.

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

References ast_debug, stimulate_attended_transfer(), and STIMULUS_TRANSFERER_HANGUP.

Referenced by bridge_personality_atxfer_push().

2798 {
2799  struct attended_transfer_properties *props = hook_pvt;
2800 
2801  ast_debug(1, "Transferer on attended transfer %p hung up\n", props);
2803  return 0;
2804 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static void stimulate_attended_transfer(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
Collection of data related to an attended transfer attempt.

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

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

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 }
enum bridge_channel_state state
struct ast_bridge * bridge
Bridge this channel is participating in.
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:490
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:493
struct ast_bridge_channels_list channels
Definition: bridge.h:371
Structure that contains information regarding a channel in a bridge.
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
Lock the bridge associated with the bridge channel.
Definition: search.h:40

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

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

Referenced by feature_blind_transfer().

3463 {
3464  struct ast_channel *transferer_channel = user_data_wrapper->data;
3465 
3466  if (transfer_type == AST_BRIDGE_TRANSFER_MULTI_PARTY) {
3467  copy_caller_data(new_channel, transferer_channel);
3468  }
3469 }
Main Channel structure associated with a channel.
static void copy_caller_data(struct ast_channel *dest, struct ast_channel *caller)

◆ blond_enter()

static int blond_enter ( struct attended_transfer_properties props)
static

Definition at line 2322 of file bridge_basic.c.

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

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 }
Main Channel structure associated with a channel.
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.
struct ast_bridge * transferee_bridge
struct ast_channel * transfer_target
static void ringing(struct ast_channel *chan)
Helper method to send a ringing indication to a channel in a bridge.
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2949
struct ast_bridge * target_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
struct ast_channel * transferer

◆ blond_nonfinal_enter()

static int blond_nonfinal_enter ( struct attended_transfer_properties props)
static

Definition at line 2338 of file bridge_basic.c.

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.

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 }
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2938
static int blond_enter(struct attended_transfer_properties *props)
struct ast_channel * transfer_target
struct ast_channel * recall_target
Recall superstate.
Definition: bridge_basic.c:768
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2927
enum attended_transfer_superstate superstate

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

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

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 }
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2938
Resume state.
Definition: bridge_basic.c:903
static const struct attended_transfer_state_properties state_properties[]
#define LOG_WARNING
Definition: logger.h:274
Fail state.
const char * stimulus_strs[]
String representations of the various stimuli.
static void remove_attended_transfer_stimulus(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
struct ast_channel * recall_target
#define ast_log
Definition: astobj2.c:42
enum attended_transfer_state state
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2462
Recalling state.

◆ 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 Private data to attach to the personality.

Definition at line 3530 of file bridge_basic.c.

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 ast_datastore_info::type.

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

3532 {
3533  struct bridge_basic_personality *personality = bridge->personality;
3535 
3537 
3538  ao2_cleanup(personality->details[personality->current].pvt);
3539  personality->details[personality->current].pvt = NULL;
3541 
3542  personality->current = type;
3543  if (user_data) {
3544  ao2_ref(user_data, +1);
3545  }
3546  personality->details[personality->current].pvt = user_data;
3547  ast_set_flag(&bridge->feature_flags, personality->details[personality->current].bridge_flags);
3548  if (personality->details[personality->current].on_personality_change) {
3549  personality->details[personality->current].on_personality_change(bridge);
3550  }
3551 }
static const char type[]
Definition: chan_ooh323.c:109
struct ast_flags feature_flags
Definition: bridge.h:377
unsigned int bridge_flags
Definition: bridge_basic.c:317
#define ast_set_flag(p, flag)
Definition: utils.h:70
void(* on_personality_change)(struct ast_bridge *bridge)
Definition: bridge_basic.c:321
enum bridge_basic_personality_type current
Definition: bridge_basic.c:329
void * personality
Definition: bridge.h:361
#define NULL
Definition: resample.c:96
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
static void remove_hooks_on_personality_change(struct ast_bridge *bridge)
Remove appropriate hooks when basic bridge personality changes.
Definition: bridge_basic.c:720
structure that organizes different personalities for basic bridges.
Definition: bridge_basic.c:327
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:493
#define AST_FLAGS_ALL
Definition: utils.h:196
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:480
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct personality_details details[BRIDGE_BASIC_PERSONALITY_END]
Definition: bridge_basic.c:331

◆ bridge_basic_destroy()

static void bridge_basic_destroy ( struct ast_bridge self)
static

Definition at line 703 of file bridge_basic.c.

References ao2_cleanup, ast_bridge_base_v_table, and ast_bridge_methods::destroy.

Referenced by ast_bridging_init_basic().

704 {
705  struct bridge_basic_personality *personality = self->personality;
706 
707  ao2_cleanup(personality);
708 
710 }
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
structure that organizes different personalities for basic bridges.
Definition: bridge_basic.c:327
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
ast_bridge_destructor_fn destroy
Definition: bridge.h:269

◆ bridge_basic_personality_alloc()

static struct ast_bridge* bridge_basic_personality_alloc ( struct ast_bridge bridge)
static

Definition at line 3594 of file bridge_basic.c.

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

3595 {
3596  struct bridge_basic_personality *personality;
3597  int i;
3598 
3599  if (!bridge) {
3600  return NULL;
3601  }
3602 
3603  personality = ao2_alloc(sizeof(*personality), personality_destructor);
3604  if (!personality) {
3605  ao2_ref(bridge, -1);
3606  return NULL;
3607  }
3608  for (i = 0; i < BRIDGE_BASIC_PERSONALITY_END; ++i) {
3609  init_details(&personality->details[i], i);
3610  }
3612  bridge->personality = personality;
3613 
3614  return bridge;
3615 }
enum bridge_basic_personality_type current
Definition: bridge_basic.c:329
void * personality
Definition: bridge.h:361
static void init_details(struct personality_details *details, enum bridge_basic_personality_type type)
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
structure that organizes different personalities for basic bridges.
Definition: bridge_basic.c:327
struct personality_details details[BRIDGE_BASIC_PERSONALITY_END]
Definition: bridge_basic.c:331
static void personality_destructor(void *obj)

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

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

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 }
enum bridge_basic_personality_type current
Definition: bridge_basic.c:329
#define ast_assert(a)
Definition: utils.h:650
#define NULL
Definition: resample.c:96
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
structure that organizes different personalities for basic bridges.
Definition: bridge_basic.c:327
struct ast_bridge_methods * v_table
Definition: bridge_basic.c:315
void ast_bridge_channel_update_accountcodes(struct ast_bridge_channel *joining, struct ast_bridge_channel *leaving)
ast_bridge_pull_channel_fn pull
Definition: bridge.h:275
struct personality_details details[BRIDGE_BASIC_PERSONALITY_END]
Definition: bridge_basic.c:331

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

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

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 }
enum bridge_basic_personality_type current
Definition: bridge_basic.c:329
#define ast_assert(a)
Definition: utils.h:650
#define NULL
Definition: resample.c:96
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
void ast_bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
structure that organizes different personalities for basic bridges.
Definition: bridge_basic.c:327
struct ast_bridge_methods * v_table
Definition: bridge_basic.c:315
void ast_bridge_channel_update_accountcodes(struct ast_bridge_channel *joining, struct ast_bridge_channel *leaving)
ast_bridge_push_channel_fn push
Definition: bridge.h:273
struct personality_details details[BRIDGE_BASIC_PERSONALITY_END]
Definition: bridge_basic.c:331

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

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

Referenced by add_normal_hooks().

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 }
struct ast_bridge_features * features
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

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

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

Referenced by ast_bridge_features_ds_append(), and ast_bridge_features_ds_set().

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 }
static const struct ast_datastore_info dtmf_features_info
Definition: bridge_basic.c:82
unsigned int flags
Definition: utils.h:200
Structure for a data store object.
Definition: datastore.h:68
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:2390
#define NULL
Definition: resample.c:96
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
Structure used to handle boolean flags.
Definition: utils.h:199
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790
void * data
Definition: datastore.h:70
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2376

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

References ast_bridge_queue_everyone_else(), AST_CONTROL_HOLD, AST_FRAME_CONTROL, ast_frame::frametype, and NULL.

Referenced by wait_to_recall_enter(), and wait_to_retransfer_enter().

1845 {
1846  struct ast_frame hold = {
1847  .frametype = AST_FRAME_CONTROL,
1848  .subclass.integer = AST_CONTROL_HOLD,
1849  };
1850 
1851  ast_bridge_queue_everyone_else(bridge, NULL, &hold);
1852 }
static void hold(struct ast_channel *chan)
Helper method to place a channel in a bridge on hold.
#define NULL
Definition: resample.c:96
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.
Data structure associated with a single frame of data.

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

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

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_bridge_lock_both(bridge1, bridge2)
Lock two bridges.
Definition: bridge.h:500
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:2096
struct ast_bridge_channel * bridge_find_channel(struct ast_bridge *bridge, struct ast_channel *chan)
Definition: bridge.c:1469
#define NULL
Definition: resample.c:96
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:493
Structure that contains information regarding a channel in a bridge.

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

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

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

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 ast_channel_lock(chan)
Definition: channel.h:2902
#define ast_bridge_lock_both(bridge1, bridge2)
Lock two bridges.
Definition: bridge.h:500
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_channel_unlock(chan)
Definition: channel.h:2903
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:493
struct ast_channel * swap
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel&#39;s bridge pointer.
Definition: channel.c:10676
Structure that contains information regarding a channel in a bridge.
int bridge_do_move(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bridge_channel, int attempt_recovery, unsigned int optimized)
Definition: bridge.c:2362
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ bridge_personality_atxfer_pull()

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

Definition at line 2980 of file bridge_basic.c.

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

2981 {
2982  struct bridge_basic_personality *personality = self->personality;
2983  struct attended_transfer_properties *props = personality->details[personality->current].pvt;
2984 
2985  switch (props->superstate) {
2986  case SUPERSTATE_TRANSFER:
2987  transfer_pull(self, bridge_channel, props);
2988  break;
2989  case SUPERSTATE_RECALL:
2990  recall_pull(self, bridge_channel, props);
2991  break;
2992  }
2993 }
enum bridge_basic_personality_type current
Definition: bridge_basic.c:329
static void transfer_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct attended_transfer_properties *props)
Recall superstate.
Definition: bridge_basic.c:768
structure that organizes different personalities for basic bridges.
Definition: bridge_basic.c:327
Transfer superstate.
Definition: bridge_basic.c:753
static void recall_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct attended_transfer_properties *props)
struct personality_details details[BRIDGE_BASIC_PERSONALITY_END]
Definition: bridge_basic.c:331
enum attended_transfer_superstate superstate
Collection of data related to an attended transfer attempt.

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

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

2856 {
2857  const char *abort_dtmf;
2858  const char *complete_dtmf;
2859  const char *threeway_dtmf;
2860  const char *swap_dtmf;
2861  struct bridge_basic_personality *personality = self->personality;
2862 
2863  if (!ast_channel_has_role(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME)) {
2864  return 0;
2865  }
2866 
2867  abort_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "abort");
2868  complete_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "complete");
2869  threeway_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "threeway");
2870  swap_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "swap");
2871 
2872  if (!ast_strlen_zero(abort_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2873  abort_dtmf, atxfer_abort, personality->details[personality->current].pvt, NULL,
2875  return -1;
2876  }
2877  if (!ast_strlen_zero(complete_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2878  complete_dtmf, atxfer_complete, personality->details[personality->current].pvt, NULL,
2880  return -1;
2881  }
2882  if (!ast_strlen_zero(threeway_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2883  threeway_dtmf, atxfer_threeway, personality->details[personality->current].pvt, NULL,
2885  return -1;
2886  }
2887  if (!ast_strlen_zero(swap_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
2888  swap_dtmf, atxfer_swap, personality->details[personality->current].pvt, NULL,
2890  return -1;
2891  }
2893  personality->details[personality->current].pvt, NULL,
2895  return -1;
2896  }
2897 
2898  return 0;
2899 }
struct ast_bridge_features * features
enum bridge_basic_personality_type current
Definition: bridge_basic.c:329
#define NULL
Definition: resample.c:96
static int atxfer_complete(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses complete sequence.
static int atxfer_threeway(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses threeway sequence.
int ast_channel_has_role(struct ast_channel *channel, const char *role_name)
Check if a role exists on a channel.
Definition: bridge_roles.c:398
static int atxfer_abort(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses abort sequence.
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:3328
#define AST_TRANSFERER_ROLE_NAME
Definition: bridge_basic.h:36
#define ast_strlen_zero(a)
Definition: muted.c:73
structure that organizes different personalities for basic bridges.
Definition: bridge_basic.c:327
static int atxfer_transferer_hangup(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Hangup hook for transferer channel.
static int atxfer_swap(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses swap sequence.
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:3245
struct ast_channel * chan
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:403
struct personality_details details[BRIDGE_BASIC_PERSONALITY_END]
Definition: bridge_basic.c:331

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

References add_normal_hooks().

Referenced by ast_bridging_init_basic().

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

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

References ast_bridge_queue_everyone_else(), AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_frame::frametype, and NULL.

Referenced by recalling_enter().

1832 {
1833  struct ast_frame ringing = {
1834  .frametype = AST_FRAME_CONTROL,
1835  .subclass.integer = AST_CONTROL_RINGING,
1836  };
1837 
1838  ast_bridge_queue_everyone_else(bridge, NULL, &ringing);
1839 }
#define NULL
Definition: resample.c:96
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 ringing(struct ast_channel *chan)
Helper method to send a ringing indication to a channel in a bridge.
Data structure associated with a single frame of data.

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

References ast_bridge_queue_everyone_else(), AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, ast_frame::frametype, and NULL.

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

1858 {
1859  struct ast_frame unhold = {
1860  .frametype = AST_FRAME_CONTROL,
1861  .subclass.integer = AST_CONTROL_UNHOLD,
1862  };
1863 
1864  ast_bridge_queue_everyone_else(bridge, NULL, &unhold);
1865 }
#define NULL
Definition: resample.c:96
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 unhold(struct ast_channel *chan)
Helper method to take a channel in a bridge off hold.
Data structure associated with a single frame of data.

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

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

Referenced by ast_bridge_features_ds_set_string().

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
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285

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

References ast_get_builtin_feature(), lock, and SCOPED_CHANNELLOCK.

Referenced by builtin_features_helper().

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
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
ast_mutex_t lock
Definition: app_meetme.c:1091
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.

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

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

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 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
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:3428
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
#define ast_strlen_zero(a)
Definition: muted.c:73
static int builtin_feature_get_exten(struct ast_channel *chan, const char *feature_name, char *buf, size_t len)
Definition: bridge_basic.c:346
const char * ast_channel_name(const struct ast_channel *chan)
#define AST_FEATURE_MAX_LEN

◆ calling_target_enter()

static int calling_target_enter ( struct attended_transfer_properties props)
static

Definition at line 2100 of file bridge_basic.c.

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

2101 {
2102  bridge_move(props->target_bridge, props->transferee_bridge, props->transferer, NULL);
2103  return 0;
2104 }
struct ast_bridge * transferee_bridge
#define NULL
Definition: resample.c:96
struct ast_bridge * target_bridge
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.
struct ast_channel * 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 2106 of file bridge_basic.c.

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

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.
Rebridge state.
Definition: bridge_basic.c:870
static const struct attended_transfer_state_properties state_properties[]
#define LOG_WARNING
Definition: logger.h:274
struct ast_bridge * transferee_bridge
Fail state.
const char * stimulus_strs[]
String representations of the various stimuli.
Consulting state.
Definition: bridge_basic.c:957
#define ast_log
Definition: astobj2.c:42
enum attended_transfer_state state
Blond non-final state.
static void publish_transfer_fail(struct attended_transfer_properties *props)
Send a stasis publication for a failed attended transfer.
Hesitant state.
Definition: bridge_basic.c:842
Blond state.
static void bridge_unhold(struct ast_bridge *bridge)
Helper method to send an unhold frame to all channels in a bridge.
struct ast_channel * transferer
Threeway state.
Definition: bridge_basic.c:929

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

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

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 }
struct attended_transfer_properties::@347 stimulus_queue
struct stimulus_list * next
ast_mutex_t lock
Definition: app_meetme.c:1091
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
#define ast_free(a)
Definition: astmm.h:182

◆ common_recall_channel_setup()

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

Definition at line 2433 of file bridge_basic.c.

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

Referenced by recalling_enter(), and retransfer_enter().

2434 {
2435  ast_callid callid;
2436 
2437  callid = ast_read_threadstorage_callid();
2438  if (callid) {
2439  ast_channel_callid_set(recall, callid);
2440  }
2441 
2442  ast_channel_inherit_variables(transferer, recall);
2443  ast_channel_datastore_inherit(transferer, recall);
2444 
2445  /*
2446  * Stage a snapshot to ensure that a snapshot is always done
2447  * on the recall channel so earler COLP and CLID setup will
2448  * get published.
2449  */
2453 }
unsigned int ast_callid
Definition: logger.h:87
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:1949
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2359
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_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:6425
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
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:6765
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)

◆ complete_enter()

static int complete_enter ( struct attended_transfer_properties props)
static

Definition at line 2306 of file bridge_basic.c.

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.

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 }
Main Channel structure associated with a channel.
static void publish_transfer_success(struct attended_transfer_properties *props, struct ast_channel *transferee_channel, struct ast_channel *target_channel)
Send a stasis publication for a successful attended transfer.
const ast_string_field xfersound
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.
struct ast_bridge * transferee_bridge
struct ast_channel * transfer_target
static void play_sound(struct ast_channel *chan, const char *sound)
Helper method to play a sound on a channel in a bridge.
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2949
struct ast_bridge * target_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
struct ast_channel * transferer

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

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

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 }
static void bridge_basic_change_personality(struct ast_bridge *bridge, enum bridge_basic_personality_type type, void *user_data)
Change basic bridge personality.
static void play_failsound(struct ast_channel *chan)
Helper method to play a fail sound on a channel in a bridge.
Rebridge state.
Definition: bridge_basic.c:870
static const struct attended_transfer_state_properties state_properties[]
static void hold(struct ast_channel *chan)
Helper method to place a channel in a bridge on hold.
Complete state.
#define LOG_WARNING
Definition: logger.h:274
struct ast_bridge * transferee_bridge
Fail state.
const char * stimulus_strs[]
String representations of the various stimuli.
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
enum attended_transfer_state state
void ast_bridge_merge_inhibit(struct ast_bridge *bridge, int request)
Adjust the bridge merge inhibit request count.
Definition: bridge.c:3061
Double-checking state.
Definition: bridge_basic.c:987
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_bridge * target_bridge
static void unhold(struct ast_channel *chan)
Helper method to take a channel in a bridge off hold.
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.
static void bridge_unhold(struct ast_bridge *bridge)
Helper method to send an unhold frame to all channels in a bridge.
struct ast_channel * transferer
Threeway state.
Definition: bridge_basic.c:929

◆ copy_caller_data()

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

Definition at line 3244 of file bridge_basic.c.

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

3245 {
3246  ast_channel_lock_both(caller, dest);
3248  ast_channel_inherit_variables(caller, dest);
3249  ast_channel_datastore_inherit(caller, dest);
3250  ast_channel_unlock(dest);
3251  ast_channel_unlock(caller);
3252 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2359
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2903
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:6765
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2909
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:8282

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

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(), copy_caller_data(), NULL, and pbx_builtin_setvar_helper().

Referenced by feature_attended_transfer().

3256 {
3257  struct ast_channel *chan;
3258  int cause;
3259 
3260  /* Now we request a local channel to prepare to call the destination */
3261  chan = ast_request("Local", ast_channel_nativeformats(caller), NULL, caller, destination,
3262  &cause);
3263  if (!chan) {
3264  return NULL;
3265  }
3266 
3267  ast_channel_lock_both(chan, caller);
3268 
3270 
3271  /* Who is transferring the call. */
3272  pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", ast_channel_name(caller));
3273 
3275 
3276  ast_channel_unlock(chan);
3277  ast_channel_unlock(caller);
3278 
3279  /* Before we actually dial out let's inherit appropriate information. */
3280  copy_caller_data(chan, caller);
3281 
3282  return chan;
3283 }
Main Channel structure associated with a channel.
#define NULL
Definition: resample.c:96
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:6343
static void copy_caller_data(struct ast_channel *dest, struct ast_channel *caller)
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:6425
#define ast_channel_unlock(chan)
Definition: channel.h:2903
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:4404
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...
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2909
const char * ast_channel_name(const struct ast_channel *chan)

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

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

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 }
static void play_failsound(struct ast_channel *chan)
Helper method to play a fail sound on a channel in a bridge.
Resume state.
Definition: bridge_basic.c:903
static const struct attended_transfer_state_properties state_properties[]
static void hold(struct ast_channel *chan)
Helper method to place a channel in a bridge on hold.
Complete state.
#define LOG_WARNING
Definition: logger.h:274
struct ast_bridge * transferee_bridge
Fail state.
const char * stimulus_strs[]
String representations of the various stimuli.
Consulting state.
Definition: bridge_basic.c:957
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
enum attended_transfer_state state
struct ast_bridge * target_bridge
static void publish_transfer_fail(struct attended_transfer_properties *props)
Send a stasis publication for a failed attended transfer.
static void unhold(struct ast_channel *chan)
Helper method to take a channel in a bridge off hold.
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.
static void bridge_unhold(struct ast_bridge *bridge)
Helper method to send an unhold frame to all channels in a bridge.
struct ast_channel * transferer
Threeway state.
Definition: bridge_basic.c:929

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

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

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 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define ast_test_flag(p, flag)
Definition: utils.h:63
long int flag
Definition: f2c.h:83

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

References dynamic_dtmf_hook_data::app_args_offset, 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().

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:1771
static int dynamic_dtmf_hook_trip(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Definition: bridge_basic.c:476
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_free(a)
Definition: astmm.h:182
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:3245

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

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

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 }
Main Channel structure associated with a channel.
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.
#define NULL
Definition: resample.c:96
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_channel * chan

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

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

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 }
#define ast_channel_lock(chan)
Definition: channel.h:2902
#define ast_test_flag(p, flag)
Definition: utils.h:63
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.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define ast_channel_unlock(chan)
Definition: channel.h:2903
static void dynamic_dtmf_hook_callback(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
Definition: bridge_basic.c:436
struct ast_channel * chan
const char * ast_channel_name(const struct ast_channel *chan)

◆ fail_enter()

static int fail_enter ( struct attended_transfer_properties props)
static

Definition at line 2727 of file bridge_basic.c.

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

2728 {
2729  if (props->transferee_bridge) {
2731  props->transferee_bridge = NULL;
2732  }
2733  return 0;
2734 }
struct ast_bridge * transferee_bridge
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
#define NULL
Definition: resample.c:96

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

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

3296 {
3297  struct ast_bridge_features_attended_transfer *attended_transfer = hook_pvt;
3298  struct attended_transfer_properties *props;
3299  struct ast_bridge *bridge;
3300  char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
3301  char exten[AST_MAX_EXTENSION] = "";
3302  pthread_t thread;
3303 
3304  /* Inhibit the bridge before we do anything else. */
3305  bridge = ast_bridge_channel_merge_inhibit(bridge_channel, +1);
3306 
3307  ast_verb(3, "Channel %s: Started DTMF attended transfer.\n",
3308  ast_channel_name(bridge_channel->chan));
3309 
3310  if (strcmp(bridge->v_table->name, "basic")) {
3311  ast_log(LOG_ERROR, "Channel %s: Attended transfer attempted on unsupported bridge type '%s'.\n",
3312  ast_channel_name(bridge_channel->chan), bridge->v_table->name);
3313  ast_bridge_merge_inhibit(bridge, -1);
3314  ao2_ref(bridge, -1);
3315  return 0;
3316  }
3317 
3318  /* Was the bridge inhibited before we inhibited it? */
3319  if (1 < bridge->inhibit_merge) {
3320  /*
3321  * The peer likely initiated attended transfer at the same time
3322  * and we lost the race.
3323  */
3324  ast_verb(3, "Channel %s: Bridge '%s' does not permit merging at this time.\n",
3325  ast_channel_name(bridge_channel->chan), bridge->uniqueid);
3326  ast_bridge_merge_inhibit(bridge, -1);
3327  ao2_ref(bridge, -1);
3328  return 0;
3329  }
3330 
3331  props = attended_transfer_properties_alloc(bridge_channel->chan,
3332  attended_transfer ? attended_transfer->context : NULL);
3333  if (!props) {
3334  ast_log(LOG_ERROR, "Channel %s: Unable to allocate control structure for performing attended transfer.\n",
3335  ast_channel_name(bridge_channel->chan));
3336  ast_bridge_merge_inhibit(bridge, -1);
3337  ao2_ref(bridge, -1);
3338  return 0;
3339  }
3340 
3341  props->transferee_bridge = bridge;
3342 
3343  if (add_transferer_role(props->transferer, attended_transfer)) {
3344  ast_log(LOG_ERROR, "Channel %s: Unable to set transferrer bridge role.\n",
3345  ast_channel_name(bridge_channel->chan));
3347  return 0;
3348  }
3349 
3350  ast_bridge_channel_write_hold(bridge_channel, NULL);
3351 
3352  /* Grab the extension to transfer to */
3353  if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), props->context)) {
3354  /*
3355  * XXX The warning here really should be removed. While the
3356  * message is accurate, this is a normal exit for when the user
3357  * fails to specify a valid transfer target. e.g., The user
3358  * hungup, didn't dial any digits, or dialed an invalid
3359  * extension.
3360  */
3361  ast_log(LOG_WARNING, "Channel %s: Unable to acquire target extension for attended transfer.\n",
3362  ast_channel_name(bridge_channel->chan));
3363  ast_bridge_channel_write_unhold(bridge_channel);
3365  return 0;
3366  }
3367 
3368  ast_string_field_set(props, exten, exten);
3369 
3370  /* Fill the variable with the extension and context we want to call */
3371  snprintf(destination, sizeof(destination), "%s@%s", props->exten, props->context);
3372 
3373  ast_debug(1, "Channel %s: Attended transfer target '%s'\n",
3374  ast_channel_name(bridge_channel->chan), destination);
3375 
3376  /* Get a channel that is the destination we wish to call */
3377  props->transfer_target = dial_transfer(bridge_channel->chan, destination);
3378  if (!props->transfer_target) {
3379  ast_log(LOG_ERROR, "Channel %s: Unable to request outbound channel for attended transfer target.\n",
3380  ast_channel_name(bridge_channel->chan));
3381  stream_failsound(props->transferer);
3382  ast_bridge_channel_write_unhold(bridge_channel);
3384  return 0;
3385  }
3386 
3387 
3388  /* Create a bridge to use to talk to the person we are calling */
3390  if (!props->target_bridge) {
3391  ast_log(LOG_ERROR, "Channel %s: Unable to create bridge for attended transfer target.\n",
3392  ast_channel_name(bridge_channel->chan));
3393  stream_failsound(props->transferer);
3394  ast_bridge_channel_write_unhold(bridge_channel);
3395  ast_hangup(props->transfer_target);
3396  props->transfer_target = NULL;
3398  return 0;
3399  }
3401 
3402  if (attach_framehook(props, props->transfer_target)) {
3403  ast_log(LOG_ERROR, "Channel %s: Unable to attach framehook to transfer target.\n",
3404  ast_channel_name(bridge_channel->chan));
3405  stream_failsound(props->transferer);
3406  ast_bridge_channel_write_unhold(bridge_channel);
3407  ast_hangup(props->transfer_target);
3408  props->transfer_target = NULL;
3410  return 0;
3411  }
3412 
3417 
3418  if (ast_call(props->transfer_target, destination, 0)) {
3419  ast_log(LOG_ERROR, "Channel %s: Unable to place outbound call to transfer target.\n",
3420  ast_channel_name(bridge_channel->chan));
3421  stream_failsound(props->transferer);
3422  ast_bridge_channel_write_unhold(bridge_channel);
3423  ast_hangup(props->transfer_target);
3424  props->transfer_target = NULL;
3426  return 0;
3427  }
3428 
3429  /* We increase the refcount of the transfer target because ast_bridge_impart() will
3430  * steal the reference we already have. We need to keep a reference, so the only
3431  * choice is to give it a bump
3432  */
3436  ast_log(LOG_ERROR, "Channel %s: Unable to place transfer target into bridge.\n",
3437  ast_channel_name(bridge_channel->chan));
3438  stream_failsound(props->transferer);
3439  ast_bridge_channel_write_unhold(bridge_channel);
3440  ast_hangup(props->transfer_target);
3441  props->transfer_target = NULL;
3443  return 0;
3444  }
3445 
3447  ast_log(LOG_ERROR, "Channel %s: Unable to create monitoring thread for attended transfer.\n",
3448  ast_channel_name(bridge_channel->chan));
3449  stream_failsound(props->transferer);
3450  ast_bridge_channel_write_unhold(bridge_channel);
3452  return 0;
3453  }
3454 
3455  /* Once the monitoring thread has been created, it is responsible for destroying all
3456  * of the necessary components.
3457  */
3458  return 0;
3459 }
pthread_t thread
Definition: app_meetme.c:1089
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static void attended_transfer_properties_shutdown(struct attended_transfer_properties *props)
Initiate shutdown of attended transfer properties.
static void bridge_basic_change_personality(struct ast_bridge *bridge, enum bridge_basic_personality_type type, void *user_data)
Change basic bridge personality.
struct ast_bridge * ast_bridge_channel_merge_inhibit(struct ast_bridge_channel *bridge_channel, int request)
Adjust the bridge_channel&#39;s bridge merge inhibit request count.
const ast_string_field uniqueid
Definition: bridge.h:409
static int add_transferer_role(struct ast_channel *chan, struct ast_bridge_features_attended_transfer *attended_transfer)
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:503
const char * name
Definition: bridge.h:267
#define LOG_WARNING
Definition: logger.h:274
struct ast_bridge * transferee_bridge
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
Definition: channel.c:6452
static int attach_framehook(struct attended_transfer_properties *props, struct ast_channel *channel)
unsigned int inhibit_merge
Count of the active temporary requests to inhibit bridge merges. Zero if merges are allowed...
Definition: bridge.h:392
static void stream_failsound(struct ast_channel *chan)
Helper method to stream a fail sound on a channel.
const ast_string_field exten
#define NULL
Definition: resample.c:96
struct ast_channel * transfer_target
#define ast_verb(level,...)
Definition: logger.h:455
static struct ast_channel * dial_transfer(struct ast_channel *caller, const char *destination)
Helper function that creates an outgoing channel and returns it immediately.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
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:1924
void ast_bridge_merge_inhibit(struct ast_bridge *bridge, int request)
Adjust the bridge merge inhibit request count.
Definition: bridge.c:3061
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define ao2_ref(o, delta)
Definition: astobj2.h:464
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.
const struct ast_bridge_methods * v_table
Definition: bridge.h:359
struct ast_bridge * target_bridge
Structure that contains information about a bridge.
Definition: bridge.h:357
#define LOG_ERROR
Definition: logger.h:285
static void * attended_transfer_monitor_thread(void *data)
The main loop for the attended transfer monitor thread.
#define AST_MAX_CONTEXT
Definition: channel.h:136
static struct attended_transfer_properties * attended_transfer_properties_alloc(struct ast_channel *transferer, const char *context)
Allocate and initialize attended transfer properties.
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2534
Structure that contains configuration information for the attended transfer built in feature...
int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, const char *moh_class)
Write a hold frame into the bridge.
struct ast_channel * chan
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2927
const char * ast_channel_name(const struct ast_channel *chan)
const ast_string_field context
int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel)
Write an unhold frame into the bridge.
struct ast_channel * transferer
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
Collection of data related to an attended transfer attempt.

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

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

Referenced by ast_bridging_init_basic().

3473 {
3474  char xfer_exten[AST_MAX_EXTENSION] = "";
3475  struct ast_bridge_features_blind_transfer *blind_transfer = hook_pvt;
3476  const char *xfer_context;
3477  char *goto_on_blindxfr;
3478 
3479  ast_verb(3, "Channel %s: Started DTMF blind transfer.\n",
3480  ast_channel_name(bridge_channel->chan));
3481 
3482  ast_bridge_channel_write_hold(bridge_channel, NULL);
3483 
3484  ast_channel_lock(bridge_channel->chan);
3485  xfer_context = ast_strdupa(get_transfer_context(bridge_channel->chan,
3486  blind_transfer ? blind_transfer->context : NULL));
3487  goto_on_blindxfr = ast_strdupa(S_OR(pbx_builtin_getvar_helper(bridge_channel->chan,
3488  "GOTO_ON_BLINDXFR"), ""));
3489  ast_channel_unlock(bridge_channel->chan);
3490 
3491  /* Grab the extension to transfer to */
3492  if (grab_transfer(bridge_channel->chan, xfer_exten, sizeof(xfer_exten), xfer_context)) {
3493  ast_bridge_channel_write_unhold(bridge_channel);
3494  return 0;
3495  }
3496 
3497  ast_debug(1, "Channel %s: Blind transfer target '%s@%s'\n",
3498  ast_channel_name(bridge_channel->chan), xfer_exten, xfer_context);
3499 
3500  if (!ast_strlen_zero(goto_on_blindxfr)) {
3501  const char *chan_context;
3502  const char *chan_exten;
3503  int chan_priority;
3504 
3505  ast_debug(1, "Channel %s: After transfer, transferrer goes to %s\n",
3506  ast_channel_name(bridge_channel->chan), goto_on_blindxfr);
3507 
3508  ast_channel_lock(bridge_channel->chan);
3509  chan_context = ast_strdupa(ast_channel_context(bridge_channel->chan));
3510  chan_exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
3511  chan_priority = ast_channel_priority(bridge_channel->chan);
3512  ast_channel_unlock(bridge_channel->chan);
3513  ast_bridge_set_after_go_on(bridge_channel->chan,
3514  chan_context, chan_exten, chan_priority, goto_on_blindxfr);
3515  }
3516 
3517  if (ast_bridge_transfer_blind(0, bridge_channel->chan, xfer_exten, xfer_context,
3519  && !ast_strlen_zero(goto_on_blindxfr)) {
3520  ast_bridge_discard_after_goto(bridge_channel->chan);
3521  }
3522 
3523  return 0;
3524 }
#define ast_channel_lock(chan)
Definition: channel.h:2902
static const char * get_transfer_context(struct ast_channel *transferer, const char *context)
#define NULL
Definition: resample.c:96
int ast_channel_priority(const struct ast_channel *chan)
#define ast_verb(level,...)
Definition: logger.h:455
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
static void blind_transfer_cb(struct ast_channel *new_channel, struct transfer_channel_data *user_data_wrapper, enum ast_transfer_type transfer_type)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
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:4477
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
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.
void ast_bridge_discard_after_goto(struct ast_channel *chan)
Discard channel after bridge goto location.
Definition: bridge_after.c:396
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2903
int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, const char *moh_class)
Write a hold frame into the bridge.
struct ast_channel * chan
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_name(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
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:636
Structure that contains configuration information for the blind transfer built in feature...
int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel)
Write an unhold frame into the bridge.

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

References ast_channel_context(), ast_channel_macrocontext(), ast_strlen_zero, context, and pbx_builtin_getvar_helper().

Referenced by attended_transfer_properties_alloc(), and feature_blind_transfer().

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 * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(a)
Definition: muted.c:73
const char * ast_channel_context(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
const char * ast_channel_macrocontext(const struct ast_channel *chan)

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

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

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 }
#define ast_channel_lock(chan)
Definition: channel.h:2902
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.
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...
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition: channel.c:10628
Structure that contains information about a bridge.
Definition: bridge.h:357
#define ast_channel_unlock(chan)
Definition: channel.h:2903
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

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

References ast_bridge_peer(), and get_transfer_party_non_transferer_bridge().

Referenced by get_transfer_parties().

1596 {
1597  *transferer_peer = ast_bridge_peer(transferer_bridge, transferer);
1598  get_transfer_party_non_transferer_bridge(other_bridge, other_party);
1599 }
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_channel * ast_bridge_peer(struct ast_bridge *bridge, struct ast_channel *chan)
Get the channel&#39;s bridge peer only if the bridge is two-party.
Definition: bridge.c:4142

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

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

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:420
#define NULL
Definition: resample.c:96
struct ast_bridge_channels_list channels
Definition: bridge.h:371
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2927
unsigned int num_channels
Definition: bridge.h:381

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

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

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