bridge_basic.c File Reference

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

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

Include dependency graph for bridge_basic.c:

Go to the source code of this file.

Data Structures

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

Defines

#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.
void ast_bridge_basic_set_flags (struct ast_bridge *bridge, unsigned int flags)
 Set feature flags on a basic bridge.
int ast_bridge_features_ds_append (struct ast_channel *chan, struct ast_flags *flags)
 Append basic bridge DTMF feature flags on the channel.
struct ast_flagsast_bridge_features_ds_get (struct ast_channel *chan)
 Get DTMF feature flags from the channel.
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
int ast_bridge_features_ds_set (struct ast_channel *chan, struct ast_flags *flags)
 Set basic bridge DTMF feature flags datastore on the channel.
int ast_bridge_features_ds_set_string (struct ast_channel *chan, const char *features)
 Sets the features a channel will use upon being bridged.
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.
static struct
attended_transfer_properties
attended_transfer_properties_alloc (struct ast_channel *transferer, const char *context)
 Allocate and initialize attended transfer properties.
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.
static int atxfer_abort (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 DTMF hook when transferer presses abort sequence.
static int atxfer_complete (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 DTMF hook when transferer presses complete sequence.
static int atxfer_swap (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 DTMF hook when transferer presses swap sequence.
static int atxfer_threeway (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 DTMF hook when transferer presses threeway sequence.
static int atxfer_transferer_hangup (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 Hangup hook for transferer channel.
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.
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.
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.
static int 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_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.
static void bridge_unhold (struct ast_bridge *bridge)
 Helper method to send an unhold frame to all channels in a bridge.
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.
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.
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.
static int feature_blind_transfer (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 Internal built in feature for blind transfers.
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
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.
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 int grab_transfer (struct ast_channel *chan, char *exten, size_t exten_len, const char *context)
 Helper function that presents dialtone and grabs extension.
static int 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.
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_sound (struct ast_channel *chan, const char *sound)
 Helper method to play a sound on a channel in a bridge.
static void publish_transfer_fail (struct attended_transfer_properties *props)
 Send a stasis publication for a failed attended transfer.
static void 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 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.
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.
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_hooks_on_personality_change (struct ast_bridge *bridge)
 Remove appropriate hooks when basic bridge personality changes.
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.
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 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.
static int transfer_target_framehook_consume (void *data, enum ast_frame_type type)
 Callback function which informs upstream if we are consuming a frame of a specific type.
static 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.
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.
static struct ast_datastore_info dtmf_features_info
struct ast_bridge_methods personality_atxfer_v_table
struct ast_bridge_methods personality_normal_v_table
static struct
attended_transfer_state_properties 
state_properties []
const char * stimulus_strs []
 String representations of the various stimuli.


Detailed Description

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

Author:
Richard Mudgett <rmudgett@digium.com>
See Also:

Definition in file bridge_basic.c.


Define Documentation

#define NORMAL_FLAGS

#define TRANSFER_FLAGS   AST_BRIDGE_FLAG_SMART

Definition at line 56 of file bridge_basic.c.

Referenced by init_details().


Enumeration Type Documentation

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

00777                              {
00778    /*!
00779     * \brief Calling Target state
00780     *
00781     * This state describes the initial state of a transfer. The transferer
00782     * waits in the transfer target's bridge for the transfer target to answer.
00783     *
00784     * Superstate: Transfer
00785     *
00786     * Preconditions:
00787     * 1) Transfer target is RINGING
00788     * 2) Transferer is in transferee bridge
00789     * 3) Transferee is on hold
00790     *
00791     * Transitions to TRANSFER_CALLING_TARGET:
00792     * 1) This is the initial state for an attended transfer.
00793     * 2) TRANSFER_HESITANT: Transferer presses DTMF swap sequence
00794     *
00795     * State operation:
00796     * The transferer is moved from the transferee bridge into the transfer
00797     * target bridge.
00798     *
00799     * Transitions from TRANSFER_CALLING_TARGET:
00800     * 1) TRANSFER_FAIL: Transferee hangs up.
00801     * 2) TRANSFER_BLOND: Transferer hangs up or presses DTMF swap sequence
00802     * and configured atxferdropcall setting is yes.
00803     * 3) TRANSFER_BLOND_NONFINAL: Transferer hangs up or presses DTMF swap
00804     * sequence and configured atxferdroppcall setting is no.
00805     * 4) TRANSFER_CONSULTING: Transfer target answers the call.
00806     * 5) TRANSFER_REBRIDGE: Transfer target hangs up, call to transfer target
00807     * times out, or transferer presses DTMF abort sequence.
00808     * 6) TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence.
00809     * 7) TRANSFER_HESITANT: Transferer presses DTMF swap sequence.
00810     */
00811    TRANSFER_CALLING_TARGET,
00812    /*!
00813     * \brief Hesitant state
00814     *
00815     * This state only arises if when waiting for the transfer target to
00816     * answer, the transferer presses the DTMF swap sequence. This will
00817     * cause the transferer to be rebridged with the transferee temporarily.
00818     *
00819     * Superstate: Transfer
00820     *
00821     * Preconditions:
00822     * 1) Transfer target is in ringing state
00823     * 2) Transferer is in transfer target bridge
00824     * 3) Transferee is on hold
00825     *
00826     * Transitions to TRANSFER_HESITANT:
00827     * 1) TRANSFER_CALLING_TARGET: Transferer presses DTMF swap sequence.
00828     *
00829     * State operation:
00830     * The transferer is moved from the transfer target bridge into the
00831     * transferee bridge, and the transferee is taken off hold.
00832     *
00833     * Transitions from TRANSFER_HESITANT:
00834     * 1) TRANSFER_FAIL: Transferee hangs up
00835     * 2) TRANSFER_BLOND: Transferer hangs up or presses DTMF swap sequence
00836     * and configured atxferdropcall setting is yes.
00837     * 3) TRANSFER_BLOND_NONFINAL: Transferer hangs up or presses DTMF swap
00838     * sequence and configured atxferdroppcall setting is no.
00839     * 4) TRANSFER_DOUBLECHECKING: Transfer target answers the call
00840     * 5) TRANSFER_RESUME: Transfer target hangs up, call to transfer target
00841     * times out, or transferer presses DTMF abort sequence.
00842     * 6) TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence.
00843     * 7) TRANSFER_CALLING_TARGET: Transferer presses DTMF swap sequence.
00844     */
00845    TRANSFER_HESITANT,
00846    /*!
00847     * \brief Rebridge state
00848     *
00849     * This is a terminal state that indicates that the transferer needs
00850     * to move back to the transferee's bridge. This is a failed attended
00851     * transfer result.
00852     *
00853     * Superstate: Transfer
00854     *
00855     * Preconditions:
00856     * 1) Transferer is in transfer target bridge
00857     * 2) Transferee is on hold
00858     *
00859     * Transitions to TRANSFER_REBRIDGE:
00860     * 1) TRANSFER_CALLING_TARGET: Transfer target hangs up, call to transfer target
00861     * times out, or transferer presses DTMF abort sequence.
00862     * 2) TRANSFER_STATE_CONSULTING: Transfer target hangs up, or transferer presses
00863     * DTMF abort sequence.
00864     *
00865     * State operation:
00866     * The transferer channel is moved from the transfer target bridge to the
00867     * transferee bridge. The transferee is taken off hold. A stasis transfer
00868     * message is published indicating a failed attended transfer.
00869     *
00870     * Transitions from TRANSFER_REBRIDGE:
00871     * None
00872     */
00873    TRANSFER_REBRIDGE,
00874    /*!
00875     * \brief Resume state
00876     *
00877     * This is a terminal state that indicates that the party bridged with the
00878     * transferee is the final party to be bridged with that transferee. This state
00879     * may come about due to a successful recall or due to a failed transfer.
00880     *
00881     * Superstate: Transfer or Recall
00882     *
00883     * Preconditions:
00884     * In Transfer Superstate:
00885     * 1) Transferer is in transferee bridge
00886     * 2) Transferee is not on hold
00887     * In Recall Superstate:
00888     * 1) The recall target is in the transferee bridge
00889     * 2) Transferee is not on hold
00890     *
00891     * Transitions to TRANSFER_RESUME:
00892     * TRANSFER_HESITANT: Transfer target hangs up, call to transfer target times out,
00893     * or transferer presses DTMF abort sequence.
00894     * TRANSFER_DOUBLECHECKING: Transfer target hangs up or transferer presses DTMF
00895     * abort sequence.
00896     * TRANSFER_BLOND_NONFINAL: Recall target answers
00897     * TRANSFER_RECALLING: Recall target answers
00898     * TRANSFER_RETRANSFER: Recall target answers
00899     *
00900     * State operations:
00901     * None
00902     *
00903     * Transitions from TRANSFER_RESUME:
00904     * None
00905     */
00906    TRANSFER_RESUME,
00907    /*!
00908     * \brief Threeway state
00909     *
00910     * This state results when the transferer wishes to have all parties involved
00911     * in a transfer to be in the same bridge together.
00912     *
00913     * Superstate: Transfer
00914     *
00915     * Preconditions:
00916     * 1) Transfer target state is either RINGING or UP
00917     * 2) Transferer is in either bridge
00918     * 3) Transferee is not on hold
00919     *
00920     * Transitions to TRANSFER_THREEWAY:
00921     * 1) TRANSFER_CALLING_TARGET: Transferer presses DTMF threeway sequence.
00922     * 2) TRANSFER_HESITANT: Transferer presses DTMF threeway sequence.
00923     * 3) TRANSFER_CONSULTING: Transferer presses DTMF threeway sequence.
00924     * 4) TRANSFER_DOUBLECHECKING: Transferer presses DTMF threeway sequence.
00925     *
00926     * State operation:
00927     * The transfer target bridge is merged into the transferee bridge.
00928     *
00929     * Transitions from TRANSFER_THREEWAY:
00930     * None.
00931     */
00932    TRANSFER_THREEWAY,
00933    /*!
00934     * \brief Consulting state
00935     *
00936     * This state describes the case where the transferer and transfer target
00937     * are able to converse in the transfer target's bridge prior to completing
00938     * the transfer.
00939     *
00940     * Superstate: Transfer
00941     *
00942     * Preconditions:
00943     * 1) Transfer target is UP
00944     * 2) Transferer is in target bridge
00945     * 3) Transferee is on hold
00946     *
00947     * Transitions to TRANSFER_CONSULTING:
00948     * 1) TRANSFER_CALLING_TARGET: Transfer target answers.
00949     * 2) TRANSFER_DOUBLECHECKING: Transferer presses DTMF swap sequence.
00950     *
00951     * State operations:
00952     * None.
00953     *
00954     * Transitions from TRANSFER_CONSULTING:
00955     * TRANSFER_COMPLETE: Transferer hangs up or transferer presses DTMF complete sequence.
00956     * TRANSFER_REBRIDGE: Transfer target hangs up or transferer presses DTMF abort sequence.
00957     * TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence.
00958     * TRANSFER_DOUBLECHECKING: Transferer presses DTMF swap sequence.
00959     */
00960    TRANSFER_CONSULTING,
00961    /*!
00962     * \brief Double-checking state
00963     *
00964     * This state describes the case where the transferer and transferee are
00965     * able to converse in the transferee's bridge prior to completing the transfer. The
00966     * difference between this and TRANSFER_HESITANT is that the transfer target is
00967     * UP in this case.
00968     *
00969     * Superstate: Transfer
00970     *
00971     * Preconditions:
00972     * 1) Transfer target is UP and on hold
00973     * 2) Transferer is in transferee bridge
00974     * 3) Transferee is off hold
00975     *
00976     * Transitions to TRANSFER_DOUBLECHECKING:
00977     * 1) TRANSFER_HESITANT: Transfer target answers.
00978     * 2) TRANSFER_CONSULTING: Transferer presses DTMF swap sequence.
00979     *
00980     * State operations:
00981     * None.
00982     *
00983     * Transitions from TRANSFER_DOUBLECHECKING:
00984     * 1) TRANSFER_FAIL: Transferee hangs up.
00985     * 2) TRANSFER_COMPLETE: Transferer hangs up or presses DTMF complete sequence.
00986     * 3) TRANSFER_RESUME: Transfer target hangs up or transferer presses DTMF abort sequence.
00987     * 4) TRANSFER_THREEWAY: Transferer presses DTMF threeway sequence.
00988     * 5) TRANSFER_CONSULTING: Transferer presses the DTMF swap sequence.
00989     */
00990    TRANSFER_DOUBLECHECKING,
00991    /*!
00992     * \brief Complete state
00993     *
00994     * This is a terminal state where a transferer has successfully completed an attended
00995     * transfer. This state's goal is to get the transfer target and transferee into
00996     * the same bridge and the transferer off the call.
00997     *
00998     * Superstate: Transfer
00999     *
01000     * Preconditions:
01001     * 1) Transfer target is UP and off hold.
01002     * 2) Transferer is in either bridge.
01003     * 3) Transferee is off hold.
01004     *
01005     * Transitions to TRANSFER_COMPLETE:
01006     * 1) TRANSFER_CONSULTING: transferer hangs up or presses the DTMF complete sequence.
01007     * 2) TRANSFER_DOUBLECHECKING: transferer hangs up or presses the DTMF complete sequence.
01008     *
01009     * State operation:
01010     * The transfer target bridge is merged into the transferee bridge. The transferer
01011     * channel is kicked out of the bridges as part of the merge.
01012     *
01013     * State operations:
01014     * 1) Merge the transfer target bridge into the transferee bridge,
01015     * excluding the transferer channel from the merge.
01016     * 2) Publish a stasis transfer message.
01017     *
01018     * Exit operations:
01019     * This is a terminal state, so there are no exit operations.
01020     */
01021    TRANSFER_COMPLETE,
01022    /*!
01023     * \brief Blond state
01024     *
01025     * This is a terminal state where a transferer has completed an attended transfer prior
01026     * to the transfer target answering. This state is only entered if atxferdropcall
01027     * is set to 'yes'. This is considered to be a successful attended transfer.
01028     *
01029     * Superstate: Transfer
01030     *
01031     * Preconditions:
01032     * 1) Transfer target is RINGING.
01033     * 2) Transferer is in either bridge.
01034     * 3) Transferee is off hold.
01035     *
01036     * Transitions to TRANSFER_BLOND:
01037     * 1) TRANSFER_CALLING_TARGET: Transferer hangs up or presses the DTMF complete sequence.
01038     *    atxferdropcall is set to 'yes'.
01039     * 2) TRANSFER_HESITANT: Transferer hangs up or presses the DTMF complete sequence.
01040     *    atxferdropcall is set to 'yes'.
01041     *
01042     * State operations:
01043     * The transfer target bridge is merged into the transferee bridge. The transferer
01044     * channel is kicked out of the bridges as part of the merge. A stasis transfer
01045     * publication is sent indicating a successful transfer.
01046     *
01047     * Transitions from TRANSFER_BLOND:
01048     * None
01049     */
01050    TRANSFER_BLOND,
01051    /*!
01052     * \brief Blond non-final state
01053     *
01054     * This state is very similar to the TRANSFER_BLOND state, except that
01055     * this state is entered when atxferdropcall is set to 'no'. This is the
01056     * initial state of the Recall superstate, so state operations mainly involve
01057     * moving to the Recall superstate. This means that the transfer target, that
01058     * is currently ringing is now known as the recall target.
01059     *
01060     * Superstate: Recall
01061     *
01062     * Preconditions:
01063     * 1) Recall target is RINGING.
01064     * 2) Transferee is off hold.
01065     *
01066     * Transitions to TRANSFER_BLOND_NONFINAL:
01067     * 1) TRANSFER_CALLING_TARGET: Transferer hangs up or presses the DTMF complete sequence.
01068     *    atxferdropcall is set to 'no'.
01069     * 2) TRANSFER_HESITANT: Transferer hangs up or presses the DTMF complete sequence.
01070     *    atxferdropcall is set to 'no'.
01071     *
01072     * State operation:
01073     * The superstate of the attended transfer is changed from Transfer to Recall.
01074     * The transfer target bridge is merged into the transferee bridge. The transferer
01075     * channel is kicked out of the bridges as part of the merge.
01076     *
01077     * Transitions from TRANSFER_BLOND_NONFINAL:
01078     * 1) TRANSFER_FAIL: Transferee hangs up
01079     * 2) TRANSFER_RESUME: Recall target answers
01080     * 3) TRANSFER_RECALLING: Recall target hangs up or time expires.
01081     */
01082    TRANSFER_BLOND_NONFINAL,
01083    /*!
01084     * \brief Recalling state
01085     *
01086     * This state is entered if the recall target from the TRANSFER_BLOND_NONFINAL
01087     * or TRANSFER_RETRANSFER states hangs up or does not answer. The goal of this
01088     * state is to call back the original transferer in an attempt to recover the
01089     * original call.
01090     *
01091     * Superstate: Recall
01092     *
01093     * Preconditions:
01094     * 1) Recall target is down.
01095     * 2) Transferee is off hold.
01096     *
01097     * Transitions to TRANSFER_RECALLING:
01098     * 1) TRANSFER_BLOND_NONFINAL: Recall target hangs up or time expires.
01099     * 2) TRANSFER_RETRANSFER: Recall target hangs up or time expires.
01100     *    atxferloopdelay is non-zero.
01101     * 3) TRANSFER_WAIT_TO_RECALL: Time expires.
01102     *
01103     * State operation:
01104     * The original transferer becomes the recall target and is called using the Dialing API.
01105     * Ringing is indicated to the transferee.
01106     *
01107     * Transitions from TRANSFER_RECALLING:
01108     * 1) TRANSFER_FAIL:
01109     *    a) Transferee hangs up.
01110     *    b) Recall target hangs up or time expires, and number of recall attempts exceeds atxfercallbackretries
01111     * 2) TRANSFER_WAIT_TO_RETRANSFER: Recall target hangs up or time expires.
01112     *    atxferloopdelay is non-zero.
01113     * 3) TRANSFER_RETRANSFER: Recall target hangs up or time expires.
01114     *    atxferloopdelay is zero.
01115     * 4) TRANSFER_RESUME: Recall target answers.
01116     */
01117    TRANSFER_RECALLING,
01118    /*!
01119     * \brief Wait to Retransfer state
01120     *
01121     * This state is used simply to give a bit of breathing room between attempting
01122     * to call back the original transferer and attempting to call back the original
01123     * transfer target. The transferee hears music on hold during this state as an
01124     * auditory clue that no one is currently being dialed.
01125     *
01126     * Superstate: Recall
01127     *
01128     * Preconditions:
01129     * 1) Recall target is down.
01130     * 2) Transferee is off hold.
01131     *
01132     * Transitions to TRANSFER_WAIT_TO_RETRANSFER:
01133     * 1) TRANSFER_RECALLING: Recall target hangs up or time expires.
01134     *    atxferloopdelay is non-zero.
01135     *
01136     * State operation:
01137     * The transferee is placed on hold.
01138     *
01139     * Transitions from TRANSFER_WAIT_TO_RETRANSFER:
01140     * 1) TRANSFER_FAIL: Transferee hangs up.
01141     * 2) TRANSFER_RETRANSFER: Time expires.
01142     */
01143    TRANSFER_WAIT_TO_RETRANSFER,
01144    /*!
01145     * \brief Retransfer state
01146     *
01147     * This state is used in order to attempt to call back the original
01148     * transfer target channel from the transfer. The transferee hears
01149     * ringing during this state as an auditory cue that a party is being
01150     * dialed.
01151     *
01152     * Superstate: Recall
01153     *
01154     * Preconditions:
01155     * 1) Recall target is down.
01156     * 2) Transferee is off hold.
01157     *
01158     * Transitions to TRANSFER_RETRANSFER:
01159     * 1) TRANSFER_RECALLING: Recall target hangs up or time expires.
01160     *    atxferloopdelay is zero.
01161     * 2) TRANSFER_WAIT_TO_RETRANSFER: Time expires.
01162     *
01163     * State operation:
01164     * The original transfer target is requested and is set as the recall target.
01165     * The recall target is called and placed into the transferee bridge.
01166     *
01167     * Transitions from TRANSFER_RETRANSFER:
01168     * 1) TRANSFER_FAIL: Transferee hangs up.
01169     * 2) TRANSFER_WAIT_TO_RECALL: Recall target hangs up or time expires.
01170     *    atxferloopdelay is non-zero.
01171     * 3) TRANSFER_RECALLING: Recall target hangs up or time expires.
01172     *    atxferloopdelay is zero.
01173     */
01174    TRANSFER_RETRANSFER,
01175    /*!
01176     * \brief Wait to recall state
01177     *
01178     * This state is used simply to give a bit of breathing room between attempting
01179     * to call back the original transfer target and attempting to call back the
01180     * original transferer. The transferee hears music on hold during this state as an
01181     * auditory clue that no one is currently being dialed.
01182     *
01183     * Superstate: Recall
01184     *
01185     * Preconditions:
01186     * 1) Recall target is down.
01187     * 2) Transferee is off hold.
01188     *
01189     * Transitions to TRANSFER_WAIT_TO_RECALL:
01190     * 1) TRANSFER_RETRANSFER: Recall target hangs up or time expires.
01191     *    atxferloopdelay is non-zero.
01192     *
01193     * State operation:
01194     * Transferee is placed on hold.
01195     *
01196     * Transitions from TRANSFER_WAIT_TO_RECALL:
01197     * 1) TRANSFER_FAIL: Transferee hangs up
01198     * 2) TRANSFER_RECALLING: Time expires
01199     */
01200    TRANSFER_WAIT_TO_RECALL,
01201    /*!
01202     * \brief Fail state
01203     *
01204     * This state indicates that something occurred during the transfer that
01205     * makes a graceful completion impossible. The most common stimulus for this
01206     * state is when the transferee hangs up.
01207     *
01208     * Superstate: Transfer and Recall
01209     *
01210     * Preconditions:
01211     * None
01212     *
01213     * Transitions to TRANSFER_FAIL:
01214     * 1) TRANSFER_CALLING_TARGET: Transferee hangs up.
01215     * 2) TRANSFER_HESITANT: Transferee hangs up.
01216     * 3) TRANSFER_DOUBLECHECKING: Transferee hangs up.
01217     * 4) TRANSFER_BLOND_NONFINAL: Transferee hangs up.
01218     * 5) TRANSFER_RECALLING:
01219     *    a) Transferee hangs up.
01220     *    b) Recall target hangs up or time expires, and number of
01221     *       recall attempts exceeds atxfercallbackretries.
01222     * 6) TRANSFER_WAIT_TO_RETRANSFER: Transferee hangs up.
01223     * 7) TRANSFER_RETRANSFER: Transferee hangs up.
01224     * 8) TRANSFER_WAIT_TO_RECALL: Transferee hangs up.
01225     *
01226     * State operation:
01227     * A transfer stasis publication is made indicating a failed transfer.
01228     * The transferee bridge is destroyed.
01229     *
01230     * Transitions from TRANSFER_FAIL:
01231     * None.
01232     */
01233    TRANSFER_FAIL,
01234 };

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

01867                                    {
01868    /*! This state requires that the timer be reset when entering the state */
01869    TRANSFER_STATE_FLAG_TIMER_RESET = (1 << 0),
01870    /*! This state's timer uses atxferloopdelay */
01871    TRANSFER_STATE_FLAG_TIMER_LOOP_DELAY = (1 << 1),
01872    /*! This state's timer uses atxfernoanswertimeout */
01873    TRANSFER_STATE_FLAG_ATXFER_NO_ANSWER = (1 << 2),
01874    /*! This state has a time limit associated with it */
01875    TRANSFER_STATE_FLAG_TIMED = (TRANSFER_STATE_FLAG_TIMER_RESET |
01876          TRANSFER_STATE_FLAG_TIMER_LOOP_DELAY | TRANSFER_STATE_FLAG_ATXFER_NO_ANSWER),
01877    /*! This state does not transition to any other states */
01878    TRANSFER_STATE_FLAG_TERMINAL = (1 << 3),
01879 };

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

01239                                 {
01240    /*! No stimulus. This literally can never happen. */
01241    STIMULUS_NONE,
01242    /*! All of the transferee channels have been hung up. */
01243    STIMULUS_TRANSFEREE_HANGUP,
01244    /*! The transferer has hung up. */
01245    STIMULUS_TRANSFERER_HANGUP,
01246    /*! The transfer target channel has hung up. */
01247    STIMULUS_TRANSFER_TARGET_HANGUP,
01248    /*! The transfer target channel has answered. */
01249    STIMULUS_TRANSFER_TARGET_ANSWER,
01250    /*! The recall target channel has hung up. */
01251    STIMULUS_RECALL_TARGET_HANGUP,
01252    /*! The recall target channel has answered. */
01253    STIMULUS_RECALL_TARGET_ANSWER,
01254    /*! The current state's timer has expired. */
01255    STIMULUS_TIMEOUT,
01256    /*! The transferer pressed the abort DTMF sequence. */
01257    STIMULUS_DTMF_ATXFER_ABORT,
01258    /*! The transferer pressed the complete DTMF sequence. */
01259    STIMULUS_DTMF_ATXFER_COMPLETE,
01260    /*! The transferer pressed the three-way DTMF sequence. */
01261    STIMULUS_DTMF_ATXFER_THREEWAY,
01262    /*! The transferer pressed the swap DTMF sequence. */
01263    STIMULUS_DTMF_ATXFER_SWAP,
01264 };

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

00740                                   {
00741    /*!
00742     * \brief Transfer superstate
00743     *
00744     * The attended transfer state machine begins in this superstate. The
00745     * goal of this state is for a transferer channel to facilitate a
00746     * transfer from a transferee to a transfer target.
00747     *
00748     * There are two bridges used in this superstate. The transferee bridge is
00749     * the bridge that the transferer and transferee channels originally
00750     * communicate in, and the target bridge is the bridge where the transfer
00751     * target is being dialed.
00752     *
00753     * The transferer channel is capable of moving between the bridges using
00754     * the DTMF swap sequence.
00755     */
00756    SUPERSTATE_TRANSFER,
00757    /*!
00758     * \brief Recall superstate
00759     *
00760     * The attended transfer state machine moves to this superstate if
00761     * atxferdropcall is set to "no" and the transferer channel hangs up
00762     * during a transfer. The goal in this superstate is to call back either
00763     * the transfer target or transferer and rebridge with the transferee
00764     * channel(s).
00765     *
00766     * In this superstate, there is only a single bridge used, the original
00767     * transferee bridge. Rather than distinguishing between a transferer
00768     * and transfer target, all outbound calls are toward a "recall_target"
00769     * channel.
00770     */
00771    SUPERSTATE_RECALL,
00772 };

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

00060                                    {
00061    /*! Index for "normal" basic bridge personality */
00062    BRIDGE_BASIC_PERSONALITY_NORMAL,
00063    /*! Index for attended transfer basic bridge personality */
00064    BRIDGE_BASIC_PERSONALITY_ATXFER,
00065    /*! Indicates end of enum. Must always remain the last element */
00066    BRIDGE_BASIC_PERSONALITY_END,
00067 };


Function Documentation

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

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

Definition at line 3047 of file bridge_basic.c.

References ast_bridge_features_attended_transfer::abort, ao2_cleanup, 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_bridge_features_attended_transfer::complete, lock, NULL, RAII_VAR, S_OR, SCOPED_CHANNELLOCK, ast_bridge_features_attended_transfer::swap, and ast_bridge_features_attended_transfer::threeway.

Referenced by feature_attended_transfer().

03048 {
03049    const char *atxfer_abort;
03050    const char *atxfer_threeway;
03051    const char *atxfer_complete;
03052    const char *atxfer_swap;
03053    RAII_VAR(struct ast_features_xfer_config *, xfer_cfg, NULL, ao2_cleanup);
03054    SCOPED_CHANNELLOCK(lock, chan);
03055 
03056    xfer_cfg = ast_get_chan_features_xfer_config(chan);
03057    if (!xfer_cfg) {
03058       return -1;
03059    }
03060    if (attended_transfer) {
03061       atxfer_abort = ast_strdupa(S_OR(attended_transfer->abort, xfer_cfg->atxferabort));
03062       atxfer_threeway = ast_strdupa(S_OR(attended_transfer->threeway, xfer_cfg->atxferthreeway));
03063       atxfer_complete = ast_strdupa(S_OR(attended_transfer->complete, xfer_cfg->atxfercomplete));
03064       atxfer_swap = ast_strdupa(S_OR(attended_transfer->swap, xfer_cfg->atxferswap));
03065    } else {
03066       atxfer_abort = ast_strdupa(xfer_cfg->atxferabort);
03067       atxfer_threeway = ast_strdupa(xfer_cfg->atxferthreeway);
03068       atxfer_complete = ast_strdupa(xfer_cfg->atxfercomplete);
03069       atxfer_swap = ast_strdupa(xfer_cfg->atxferswap);
03070    }
03071 
03072    return ast_channel_add_bridge_role(chan, AST_TRANSFERER_ROLE_NAME) ||
03073       ast_channel_set_bridge_role_option(chan, AST_TRANSFERER_ROLE_NAME, "abort", atxfer_abort) ||
03074       ast_channel_set_bridge_role_option(chan, AST_TRANSFERER_ROLE_NAME, "complete", atxfer_complete) ||
03075       ast_channel_set_bridge_role_option(chan, AST_TRANSFERER_ROLE_NAME, "threeway", atxfer_threeway) ||
03076       ast_channel_set_bridge_role_option(chan, AST_TRANSFERER_ROLE_NAME, "swap", atxfer_swap);
03077 }

struct ast_bridge* ast_bridge_basic_new ( void   )  [read]

Create a new basic class bridge.

Return values:
a pointer to a new bridge on success
NULL on failure
Example usage:

 struct ast_bridge *bridge;
 bridge = ast_bridge_basic_new();

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 3503 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(), app_control_dial(), ast_bridge_call_with_flags(), AST_TEST_DEFINE(), bridge_exec(), feature_attended_transfer(), and parked_call_app_exec().

03504 {
03505    struct ast_bridge *bridge;
03506 
03507    bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table);
03508    bridge = bridge_base_init(bridge,
03509       AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX
03510          | AST_BRIDGE_CAPABILITY_MULTIMIX, NORMAL_FLAGS, NULL, NULL, NULL);
03511    bridge = bridge_basic_personality_alloc(bridge);
03512    bridge = bridge_register(bridge);
03513    return bridge;
03514 }

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

03517 {
03518    SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
03519    struct bridge_basic_personality *personality = bridge->personality;
03520 
03521    personality->details[personality->current].bridge_flags |= flags;
03522    ast_set_flag(&bridge->feature_flags, flags);
03523 }

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:
chan Channel to append DTMF features datastore.
flags Builtin 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:
0 on success.
-1 on error.

Definition at line 265 of file bridge_basic.c.

References bridge_features_ds_set_full().

Referenced by pre_bridge_setup().

00266 {
00267    return bridge_features_ds_set_full(chan, flags, 0);
00268 }

struct ast_flags* ast_bridge_features_ds_get ( struct ast_channel chan  )  [read]

Get DTMF feature flags from the channel.

Since:
12.0.0
Parameters:
chan Channel 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:
flags on success.
NULL if the datastore does not exist.

Definition at line 270 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().

00271 {
00272    struct ast_datastore *datastore;
00273 
00274    datastore = ast_channel_datastore_find(chan, &dtmf_features_info, NULL);
00275    if (!datastore) {
00276       return NULL;
00277    }
00278    return datastore->data;
00279 }

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:
chan channel whose feature flags should be checked
buffer pointer string buffer where the output should be stored
buf_size size of the provided buffer (ideally enough for all features, 6+)
Return values:
0 on successful write
-1 on failure

Definition at line 210 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().

00211 {
00212    struct ast_flags *channel_flags;
00213    struct ast_flags held_copy;
00214 
00215    ast_channel_lock(chan);
00216    if (!(channel_flags = ast_bridge_features_ds_get(chan))) {
00217       ast_channel_unlock(chan);
00218       return -1;
00219    }
00220    held_copy = *channel_flags;
00221    ast_channel_unlock(chan);
00222 
00223    return dtmf_features_flags_to_string(&held_copy, buffer, buf_size);
00224 }

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:
chan Channel to set DTMF features datastore.
flags Builtin DTMF feature flags. (ast_bridge_config flags)
Note:
The channel must be locked before calling this function.
Return values:
0 on success.
-1 on error.

Definition at line 260 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().

00261 {
00262    return bridge_features_ds_set_full(chan, flags, 1);
00263 }

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:
chan Which channel to set features for
features Which feature codes to set for the channel
Return values:
0 on success
-1 on failure

Definition at line 191 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().

00192 {
00193    struct ast_flags flags = {0};
00194 
00195    if (build_dtmf_features(&flags, features)) {
00196       return -1;
00197    }
00198 
00199    ast_channel_lock(chan);
00200    if (ast_bridge_features_ds_set(chan, &flags)) {
00201       ast_channel_unlock(chan);
00202       ast_log(LOG_ERROR, "Failed to apply features datastore for '%s' to channel '%s'\n", features, ast_channel_name(chan));
00203       return -1;
00204    }
00205    ast_channel_unlock(chan);
00206 
00207    return 0;
00208 }

void ast_bridging_init_basic ( void   ) 

Initialize the basic bridge class for use by the system.

Definition at line 3525 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().

03526 {
03527    /* Setup bridge basic subclass v_table. */
03528    ast_bridge_basic_v_table = ast_bridge_base_v_table;
03529    ast_bridge_basic_v_table.name = "basic";
03530    ast_bridge_basic_v_table.push = bridge_basic_push;
03531    ast_bridge_basic_v_table.pull = bridge_basic_pull;
03532    ast_bridge_basic_v_table.destroy = bridge_basic_destroy;
03533 
03534    /*
03535     * Personality vtables don't have the same rules as
03536     * normal bridge vtables.  These vtable functions are
03537     * used as alterations to the ast_bridge_basic_v_table
03538     * method functionality and are checked for NULL before
03539     * calling.
03540     */
03541    personality_normal_v_table.name = "normal";
03542    personality_normal_v_table.push = bridge_personality_normal_push;
03543 
03544    personality_atxfer_v_table.name = "attended transfer";
03545    personality_atxfer_v_table.push = bridge_personality_atxfer_push;
03546    personality_atxfer_v_table.pull = bridge_personality_atxfer_pull;
03547 
03548    ast_bridge_features_register(AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, feature_attended_transfer, NULL);
03549    ast_bridge_features_register(AST_BRIDGE_BUILTIN_BLINDTRANSFER, feature_blind_transfer, NULL);
03550 }

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

Definition at line 3026 of file bridge_basic.c.

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

Referenced by feature_attended_transfer(), and retransfer_enter().

03027 {
03028    struct ast_framehook_interface target_interface = {
03029       .version = AST_FRAMEHOOK_INTERFACE_VERSION,
03030       .event_cb = transfer_target_framehook_cb,
03031       .destroy_cb = transfer_target_framehook_destroy_cb,
03032       .consume_cb = transfer_target_framehook_consume,
03033       .disable_inheritance = 1,
03034    };
03035 
03036    ao2_ref(props, +1);
03037    target_interface.data = props;
03038 
03039    props->target_framehook_id = ast_framehook_attach(channel, &target_interface);
03040    if (props->target_framehook_id == -1) {
03041       ao2_ref(props, -1);
03042       return -1;
03043    }
03044    return 0;
03045 }

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:
data The attended transfer properties

Definition at line 2972 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_list::stimulus, TRANSFER_STATE_FLAG_TERMINAL, attended_transfer_properties::transferer, and wait_for_stimulus().

Referenced by feature_attended_transfer().

02973 {
02974    struct attended_transfer_properties *props = data;
02975    ast_callid callid;
02976 
02977    /*
02978     * Set thread callid to the transferer's callid because we
02979     * are doing all this on that channel's behalf.
02980     */
02981    ast_channel_lock(props->transferer);
02982    callid = ast_channel_callid(props->transferer);
02983    ast_channel_unlock(props->transferer);
02984    if (callid) {
02985       ast_callid_threadassoc_add(callid);
02986    }
02987 
02988    for (;;) {
02989       enum attended_transfer_stimulus stimulus;
02990 
02991       ast_debug(1, "About to enter state %s for attended transfer %p\n", state_properties[props->state].state_name, props);
02992 
02993       if (state_properties[props->state].enter &&
02994             state_properties[props->state].enter(props)) {
02995          ast_log(LOG_ERROR, "State %s enter function returned an error for attended transfer %p\n",
02996                state_properties[props->state].state_name, props);
02997          break;
02998       }
02999 
03000       if (state_properties[props->state].flags & TRANSFER_STATE_FLAG_TERMINAL) {
03001          ast_debug(1, "State %s is a terminal state. Ending attended transfer %p\n",
03002                state_properties[props->state].state_name, props);
03003          break;
03004       }
03005 
03006       stimulus = wait_for_stimulus(props);
03007 
03008       ast_debug(1, "Received stimulus %s on attended transfer %p\n", stimulus_strs[stimulus], props);
03009 
03010       ast_assert(state_properties[props->state].exit != NULL);
03011 
03012       props->state = state_properties[props->state].exit(props, stimulus);
03013 
03014       ast_debug(1, "Told to enter state %s exit on attended transfer %p\n", state_properties[props->state].state_name, props);
03015    }
03016 
03017    attended_transfer_properties_shutdown(props);
03018 
03019    if (callid) {
03020       ast_callid_threadassoc_remove();
03021    }
03022 
03023    return NULL;
03024 }

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

Allocate and initialize attended transfer properties.

Parameters:
transferer The channel performing the attended transfer
context Suggestion for what context the transfer target extension can be found in
Return values:
NULL Failure to allocate or initialize
non-NULL Newly allocated properties

Definition at line 1414 of file bridge_basic.c.

References ao2_alloc, ao2_cleanup, 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(), attended_transfer_properties::atxfercallbackretries, attended_transfer_properties::atxferdropcall, attended_transfer_properties::atxferloopdelay, attended_transfer_properties::atxfernoanswertimeout, attended_transfer_properties::cond, get_transfer_context(), LOG_ERROR, NULL, attended_transfer_properties::original_transferer_colp, RAII_VAR, attended_transfer_properties::target_framehook_id, attended_transfer_properties::transferer, attended_transfer_properties::transferer_features, and attended_transfer_properties::xfersound.

Referenced by feature_attended_transfer().

01416 {
01417    struct attended_transfer_properties *props;
01418    char *tech;
01419    char *addr;
01420    char *serial;
01421    RAII_VAR(struct ast_features_xfer_config *, xfer_cfg, NULL, ao2_cleanup);
01422    struct ast_flags *transferer_features;
01423 
01424    props = ao2_alloc(sizeof(*props), attended_transfer_properties_destructor);
01425    if (!props || ast_string_field_init(props, 64)) {
01426       return NULL;
01427    }
01428 
01429    ast_cond_init(&props->cond, NULL);
01430 
01431    props->target_framehook_id = -1;
01432    props->transferer = ast_channel_ref(transferer);
01433 
01434    ast_channel_lock(props->transferer);
01435    xfer_cfg = ast_get_chan_features_xfer_config(props->transferer);
01436    if (!xfer_cfg) {
01437       ast_log(LOG_ERROR, "Unable to get transfer configuration from channel %s\n", ast_channel_name(props->transferer));
01438       ast_channel_unlock(props->transferer);
01439       ao2_ref(props, -1);
01440       return NULL;
01441    }
01442    transferer_features = ast_bridge_features_ds_get(props->transferer);
01443    if (transferer_features) {
01444       props->transferer_features = *transferer_features;
01445    }
01446    props->atxferdropcall = xfer_cfg->atxferdropcall;
01447    props->atxfercallbackretries = xfer_cfg->atxfercallbackretries;
01448    props->atxfernoanswertimeout = xfer_cfg->atxfernoanswertimeout;
01449    props->atxferloopdelay = xfer_cfg->atxferloopdelay;
01450    ast_string_field_set(props, context, get_transfer_context(transferer, context));
01451    ast_string_field_set(props, failsound, xfer_cfg->xferfailsound);
01452    ast_string_field_set(props, xfersound, xfer_cfg->xfersound);
01453 
01454    /*
01455     * Save the transferee's party information for any recall calls.
01456     * This is the only piece of information needed that gets overwritten
01457     * on the transferer channel by the inital call to the transfer target.
01458     */
01459    ast_party_connected_line_copy(&props->original_transferer_colp,
01460       ast_channel_connected(props->transferer));
01461 
01462    tech = ast_strdupa(ast_channel_name(props->transferer));
01463    addr = strchr(tech, '/');
01464    if (!addr) {
01465       ast_log(LOG_ERROR, "Transferer channel name does not follow typical channel naming format (tech/address)\n");
01466       ast_channel_unlock(props->transferer);
01467       ao2_ref(props, -1);
01468       return NULL;
01469    }
01470    *addr++ = '\0';
01471    serial = strrchr(addr, '-');
01472    if (serial) {
01473       *serial = '\0';
01474    }
01475    ast_string_field_set(props, transferer_type, tech);
01476    ast_string_field_set(props, transferer_addr, addr);
01477 
01478    ast_channel_unlock(props->transferer);
01479 
01480    ast_debug(1, "Allocated attended transfer properties %p for transfer from %s\n",
01481          props, ast_channel_name(props->transferer));
01482    return props;
01483 }

static void attended_transfer_properties_destructor ( void *  obj  )  [static]

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

01505 {
01506    ast_debug(1, "Shutting down attended transfer %p\n", props);
01507 
01508    if (props->transferee_bridge) {
01509       bridge_basic_change_personality(props->transferee_bridge,
01510             BRIDGE_BASIC_PERSONALITY_NORMAL, NULL);
01511       ast_bridge_merge_inhibit(props->transferee_bridge, -1);
01512    }
01513 
01514    if (props->target_bridge) {
01515       ast_bridge_destroy(props->target_bridge, 0);
01516       props->target_bridge = NULL;
01517    }
01518 
01519    if (props->transferer) {
01520       ast_channel_remove_bridge_role(props->transferer, AST_TRANSFERER_ROLE_NAME);
01521    }
01522 
01523    clear_stimulus_queue(props);
01524 
01525    ao2_cleanup(props);
01526 }

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

02677 {
02678    struct attended_transfer_properties *props = hook_pvt;
02679 
02680    ast_debug(1, "Transferer on attended transfer %p pressed abort sequence\n", props);
02681    stimulate_attended_transfer(props, STIMULUS_DTMF_ATXFER_ABORT);
02682    return 0;
02683 }

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

02691 {
02692    struct attended_transfer_properties *props = hook_pvt;
02693 
02694    ast_debug(1, "Transferer on attended transfer %p pressed complete sequence\n", props);
02695    stimulate_attended_transfer(props, STIMULUS_DTMF_ATXFER_COMPLETE);
02696    return 0;
02697 }

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

02719 {
02720    struct attended_transfer_properties *props = hook_pvt;
02721 
02722    ast_debug(1, "Transferer on attended transfer %p pressed swap sequence\n", props);
02723    stimulate_attended_transfer(props, STIMULUS_DTMF_ATXFER_SWAP);
02724    return 0;
02725 }

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

02705 {
02706    struct attended_transfer_properties *props = hook_pvt;
02707 
02708    ast_debug(1, "Transferer on attended transfer %p pressed threeway sequence\n", props);
02709    stimulate_attended_transfer(props, STIMULUS_DTMF_ATXFER_THREEWAY);
02710    return 0;
02711 }

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

References ast_debug, stimulate_attended_transfer(), and STIMULUS_TRANSFERER_HANGUP.

Referenced by bridge_personality_atxfer_push().

02733 {
02734    struct attended_transfer_properties *props = hook_pvt;
02735 
02736    ast_debug(1, "Transferer on attended transfer %p hung up\n", props);
02737    stimulate_attended_transfer(props, STIMULUS_TRANSFERER_HANGUP);
02738    return 0;
02739 }

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

Definition at line 292 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().

00293 {
00294    int bridge_count = 0;
00295    struct ast_bridge_channel *iter;
00296 
00297    ast_bridge_channel_lock_bridge(bridge_channel);
00298    AST_LIST_TRAVERSE(&bridge_channel->bridge->channels, iter, entry) {
00299       if (iter != bridge_channel && iter->state == BRIDGE_CHANNEL_STATE_WAIT) {
00300          ++bridge_count;
00301       }
00302    }
00303    if (2 <= bridge_count) {
00304       /* Just allow this channel to leave the multi-party bridge. */
00305       ast_bridge_channel_leave_bridge(bridge_channel,
00306          BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, 0);
00307    }
00308    ast_bridge_unlock(bridge_channel->bridge);
00309    return 0;
00310 }

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

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

03366 {
03367    struct ast_channel *transferer_channel = user_data_wrapper->data;
03368 
03369    if (transfer_type == AST_BRIDGE_TRANSFER_MULTI_PARTY) {
03370       copy_caller_data(new_channel, transferer_channel);
03371    }
03372 }

static int blond_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2261 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().

02262 {
02263    struct ast_channel *transferee_channel;
02264    struct ast_channel *target_channel;
02265 
02266    get_transfer_parties(props->transferer, props->transferee_bridge, props->target_bridge,
02267          &transferee_channel, &target_channel);
02268    bridge_merge(props->transferee_bridge, props->target_bridge, &props->transferer, 1);
02269    ringing(props->transfer_target);
02270    publish_transfer_success(props, transferee_channel, target_channel);
02271 
02272    ast_channel_cleanup(transferee_channel);
02273    ast_channel_cleanup(target_channel);
02274    return 0;
02275 }

static int blond_nonfinal_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2277 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.

02278 {
02279    int res;
02280    props->superstate = SUPERSTATE_RECALL;
02281    /* move the transfer target to the recall target along with its reference */
02282    props->recall_target = ast_channel_ref(props->transfer_target);
02283    res = blond_enter(props);
02284    props->transfer_target = ast_channel_unref(props->transfer_target);
02285    return res;
02286 }

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

Definition at line 2288 of file bridge_basic.c.

References ast_channel_unref, ast_log, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, LOG_WARNING, attended_transfer_properties::recall_target, 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_TIMEOUT, STIMULUS_TRANSFER_TARGET_ANSWER, STIMULUS_TRANSFER_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, STIMULUS_TRANSFERER_HANGUP, TRANSFER_FAIL, TRANSFER_RECALLING, and TRANSFER_RESUME.

02290 {
02291    switch (stimulus) {
02292    case STIMULUS_TRANSFEREE_HANGUP:
02293       return TRANSFER_FAIL;
02294    case STIMULUS_RECALL_TARGET_ANSWER:
02295       return TRANSFER_RESUME;
02296    case STIMULUS_TIMEOUT:
02297       ast_softhangup(props->recall_target, AST_SOFTHANGUP_EXPLICIT);
02298    case STIMULUS_RECALL_TARGET_HANGUP:
02299       props->recall_target = ast_channel_unref(props->recall_target);
02300       return TRANSFER_RECALLING;
02301    case STIMULUS_NONE:
02302    case STIMULUS_DTMF_ATXFER_ABORT:
02303    case STIMULUS_DTMF_ATXFER_COMPLETE:
02304    case STIMULUS_DTMF_ATXFER_THREEWAY:
02305    case STIMULUS_DTMF_ATXFER_SWAP:
02306    case STIMULUS_TRANSFERER_HANGUP:
02307    case STIMULUS_TRANSFER_TARGET_HANGUP:
02308    case STIMULUS_TRANSFER_TARGET_ANSWER:
02309    default:
02310       ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
02311             stimulus_strs[stimulus], state_properties[props->state].state_name);
02312       return props->state;
02313    }
02314 }

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:
bridge The bridge
type The personality to change the bridge to Private data to attach to the personality.

Definition at line 3416 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(), and SCOPED_LOCK.

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

03418 {
03419    struct bridge_basic_personality *personality = bridge->personality;
03420    SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
03421 
03422    remove_hooks_on_personality_change(bridge);
03423 
03424    ao2_cleanup(personality->details[personality->current].pvt);
03425    personality->details[personality->current].pvt = NULL;
03426    ast_clear_flag(&bridge->feature_flags, AST_FLAGS_ALL);
03427 
03428    personality->current = type;
03429    if (user_data) {
03430       ao2_ref(user_data, +1);
03431    }
03432    personality->details[personality->current].pvt = user_data;
03433    ast_set_flag(&bridge->feature_flags, personality->details[personality->current].bridge_flags);
03434    if (personality->details[personality->current].on_personality_change) {
03435       personality->details[personality->current].on_personality_change(bridge);
03436    }
03437 }

static void bridge_basic_destroy ( struct ast_bridge self  )  [static]

Definition at line 706 of file bridge_basic.c.

References ao2_cleanup, ast_bridge_base_v_table, and ast_bridge_methods::destroy.

Referenced by ast_bridging_init_basic().

00707 {
00708    struct bridge_basic_personality *personality = self->personality;
00709 
00710    ao2_cleanup(personality);
00711 
00712    ast_bridge_base_v_table.destroy(self);
00713 }

static struct ast_bridge* bridge_basic_personality_alloc ( struct ast_bridge bridge  )  [static, read]

Definition at line 3480 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().

03481 {
03482    struct bridge_basic_personality *personality;
03483    int i;
03484 
03485    if (!bridge) {
03486       return NULL;
03487    }
03488 
03489    personality = ao2_alloc(sizeof(*personality), personality_destructor);
03490    if (!personality) {
03491       ao2_ref(bridge, -1);
03492       return NULL;
03493    }
03494    for (i = 0; i < BRIDGE_BASIC_PERSONALITY_END; ++i) {
03495       init_details(&personality->details[i], i);
03496    }
03497    personality->current = BRIDGE_BASIC_PERSONALITY_NORMAL;
03498    bridge->personality = personality;
03499 
03500    return bridge;
03501 }

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

Definition at line 691 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().

00692 {
00693    struct bridge_basic_personality *personality = self->personality;
00694 
00695    ast_assert(personality != NULL);
00696 
00697    if (personality->details[personality->current].v_table->pull) {
00698       personality->details[personality->current].v_table->pull(self, bridge_channel);
00699    }
00700 
00701    ast_bridge_channel_update_accountcodes(NULL, bridge_channel);
00702 
00703    ast_bridge_base_v_table.pull(self, bridge_channel);
00704 }

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

Definition at line 674 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().

00675 {
00676    struct bridge_basic_personality *personality = self->personality;
00677 
00678    ast_assert(personality != NULL);
00679 
00680    if (personality->details[personality->current].v_table->push
00681       && personality->details[personality->current].v_table->push(self, bridge_channel, swap)) {
00682       return -1;
00683    }
00684 
00685    ast_bridge_channel_update_linkedids(bridge_channel, swap);
00686    ast_bridge_channel_update_accountcodes(bridge_channel, swap);
00687 
00688    return ast_bridge_base_v_table.push(self, bridge_channel, swap);
00689 }

static int bridge_basic_setup_features ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 634 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().

00635 {
00636    int res = 0;
00637 
00638    res |= setup_bridge_features_builtin(bridge_channel->features, bridge_channel->chan);
00639    res |= setup_bridge_features_dynamic(bridge_channel->features, bridge_channel->chan);
00640 
00641    return res;
00642 }

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

Definition at line 226 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().

00227 {
00228    struct ast_datastore *datastore;
00229    struct ast_flags *ds_flags;
00230 
00231    datastore = ast_channel_datastore_find(chan, &dtmf_features_info, NULL);
00232    if (datastore) {
00233       ds_flags = datastore->data;
00234       if (replace) {
00235          *ds_flags = *flags;
00236       } else {
00237          flags->flags = flags->flags | ds_flags->flags;
00238          *ds_flags = *flags;
00239       }
00240       return 0;
00241    }
00242 
00243    datastore = ast_datastore_alloc(&dtmf_features_info, NULL);
00244    if (!datastore) {
00245       return -1;
00246    }
00247 
00248    ds_flags = ast_malloc(sizeof(*ds_flags));
00249    if (!ds_flags) {
00250       ast_datastore_free(datastore);
00251       return -1;
00252    }
00253 
00254    *ds_flags = *flags;
00255    datastore->data = ds_flags;
00256    ast_channel_datastore_add(chan, datastore);
00257    return 0;
00258 }

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

01778 {
01779    struct ast_frame hold = {
01780       .frametype = AST_FRAME_CONTROL,
01781       .subclass.integer = AST_CONTROL_HOLD,
01782    };
01783 
01784    ast_bridge_queue_everyone_else(bridge, NULL, &hold);
01785 }

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

01832 {
01833    struct ast_bridge_channel **kick_bridge_channels = num_channels ?
01834       ast_alloca(num_channels * sizeof(*kick_bridge_channels)) : NULL;
01835    int i;
01836    int num_bridge_channels = 0;
01837 
01838    ast_bridge_lock_both(dest, src);
01839 
01840    for (i = 0; i < num_channels; ++i) {
01841       struct ast_bridge_channel *kick_bridge_channel;
01842 
01843       kick_bridge_channel = bridge_find_channel(src, kick_channels[i]);
01844       if (!kick_bridge_channel) {
01845          kick_bridge_channel = bridge_find_channel(dest, kick_channels[i]);
01846       }
01847 
01848       /* It's possible (and fine) for the bridge channel to be NULL at this point if the
01849        * channel has hung up already. If that happens, we can just remove it from the list
01850        * of bridge channels to kick from the bridge
01851        */
01852       if (!kick_bridge_channel) {
01853          continue;
01854       }
01855 
01856       kick_bridge_channels[num_bridge_channels++] = kick_bridge_channel;
01857    }
01858 
01859    bridge_do_merge(dest, src, kick_bridge_channels, num_bridge_channels, 0);
01860    ast_bridge_unlock(dest);
01861    ast_bridge_unlock(src);
01862 }

static int 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 1803 of file bridge_basic.c.

References ao2_cleanup, ao2_lock, ao2_unlock, ast_assert, ast_bridge_lock_both, ast_bridge_unlock, ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, bridge_do_move(), NULL, and RAII_VAR.

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

01804 {
01805    int res;
01806    RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
01807 
01808    ast_bridge_lock_both(src, dest);
01809 
01810    ast_channel_lock(channel);
01811    bridge_channel = ast_channel_get_bridge_channel(channel);
01812    ast_channel_unlock(channel);
01813 
01814    ast_assert(bridge_channel != NULL);
01815 
01816    ao2_lock(bridge_channel);
01817    bridge_channel->swap = swap;
01818    ao2_unlock(bridge_channel);
01819 
01820    res = bridge_do_move(dest, bridge_channel, 1, 0);
01821 
01822    ast_bridge_unlock(dest);
01823    ast_bridge_unlock(src);
01824 
01825    return res;
01826 }

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

Definition at line 2911 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().

02912 {
02913    struct bridge_basic_personality *personality = self->personality;
02914    struct attended_transfer_properties *props = personality->details[personality->current].pvt;
02915 
02916    switch (props->superstate) {
02917    case SUPERSTATE_TRANSFER:
02918       transfer_pull(self, bridge_channel, props);
02919       break;
02920    case SUPERSTATE_RECALL:
02921       recall_pull(self, bridge_channel, props);
02922       break;
02923    }
02924 }

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

02790 {
02791    const char *abort_dtmf;
02792    const char *complete_dtmf;
02793    const char *threeway_dtmf;
02794    const char *swap_dtmf;
02795    struct bridge_basic_personality *personality = self->personality;
02796 
02797    if (!ast_channel_has_role(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME)) {
02798       return 0;
02799    }
02800 
02801    abort_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "abort");
02802    complete_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "complete");
02803    threeway_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "threeway");
02804    swap_dtmf = ast_channel_get_role_option(bridge_channel->chan, AST_TRANSFERER_ROLE_NAME, "swap");
02805 
02806    if (!ast_strlen_zero(abort_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
02807          abort_dtmf, atxfer_abort, personality->details[personality->current].pvt, NULL,
02808          AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE | AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
02809       return -1;
02810    }
02811    if (!ast_strlen_zero(complete_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
02812          complete_dtmf, atxfer_complete, personality->details[personality->current].pvt, NULL,
02813          AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE | AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
02814       return -1;
02815    }
02816    if (!ast_strlen_zero(threeway_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
02817          threeway_dtmf, atxfer_threeway, personality->details[personality->current].pvt, NULL,
02818          AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE | AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
02819       return -1;
02820    }
02821    if (!ast_strlen_zero(swap_dtmf) && ast_bridge_dtmf_hook(bridge_channel->features,
02822          swap_dtmf, atxfer_swap, personality->details[personality->current].pvt, NULL,
02823          AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE | AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
02824       return -1;
02825    }
02826    if (ast_bridge_hangup_hook(bridge_channel->features, atxfer_transferer_hangup,
02827          personality->details[personality->current].pvt, NULL,
02828          AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE | AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
02829       return -1;
02830    }
02831 
02832    return 0;
02833 }

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

References add_normal_hooks().

Referenced by ast_bridging_init_basic().

00666 {
00667    if (add_normal_hooks(self, bridge_channel)) {
00668       return -1;
00669    }
00670 
00671    return 0;
00672 }

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

01765 {
01766    struct ast_frame ringing = {
01767       .frametype = AST_FRAME_CONTROL,
01768       .subclass.integer = AST_CONTROL_RINGING,
01769    };
01770 
01771    ast_bridge_queue_everyone_else(bridge, NULL, &ringing);
01772 }

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

01791 {
01792    struct ast_frame unhold = {
01793       .frametype = AST_FRAME_CONTROL,
01794       .subclass.integer = AST_CONTROL_UNHOLD,
01795    };
01796 
01797    ast_bridge_queue_everyone_else(bridge, NULL, &unhold);
01798 }

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

Definition at line 164 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().

00165 {
00166    const char *feature;
00167 
00168    char missing_features[strlen(features) + 1];
00169    size_t number_of_missing_features = 0;
00170 
00171    for (feature = features; *feature; feature++) {
00172       if (!isupper(*feature)) {
00173          ast_log(LOG_ERROR, "Features string '%s' rejected because it contains non-uppercase feature.\n", features);
00174          return -1;
00175       }
00176 
00177       if (set_feature_flag_from_char(flags, *feature)) {
00178          missing_features[number_of_missing_features++] = *feature;
00179       }
00180    }
00181 
00182    missing_features[number_of_missing_features] = '\0';
00183 
00184    if (number_of_missing_features) {
00185       ast_log(LOG_WARNING, "Features '%s' from features string '%s' can not be applied.\n", missing_features, features);
00186    }
00187 
00188    return 0;
00189 }

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

Definition at line 348 of file bridge_basic.c.

References ast_get_builtin_feature(), lock, and SCOPED_CHANNELLOCK.

Referenced by builtin_features_helper().

00349 {
00350    SCOPED_CHANNELLOCK(lock, chan);
00351 
00352    return ast_get_builtin_feature(chan, feature_name, buf, len);
00353 }

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

00372 {
00373    char dtmf[AST_FEATURE_MAX_LEN];
00374    int res;
00375 
00376    res = 0;
00377    if (ast_test_flag(flags, feature_flag)
00378       && !builtin_feature_get_exten(chan, feature_name, dtmf, sizeof(dtmf))
00379       && !ast_strlen_zero(dtmf)) {
00380       res = ast_bridge_features_enable(features, feature_bridge, dtmf, NULL, NULL,
00381          AST_BRIDGE_HOOK_REMOVE_ON_PULL | AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE);
00382       if (res) {
00383          ast_log(LOG_ERROR, "Channel %s: Requested DTMF feature %s not available.\n",
00384             ast_channel_name(chan), feature_name);
00385       }
00386    }
00387 
00388    return res;
00389 }

static int calling_target_enter ( struct attended_transfer_properties props  )  [static]

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

Definition at line 2039 of file bridge_basic.c.

References ast_log, attended_transfer_properties::atxferdropcall, bridge_unhold(), attended_transfer_properties::failsound, LOG_WARNING, play_sound(), 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_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.

02041 {
02042    switch (stimulus) {
02043    case STIMULUS_TRANSFEREE_HANGUP:
02044       play_sound(props->transferer, props->failsound);
02045       publish_transfer_fail(props);
02046       return TRANSFER_FAIL;
02047    case STIMULUS_DTMF_ATXFER_COMPLETE:
02048    case STIMULUS_TRANSFERER_HANGUP:
02049       bridge_unhold(props->transferee_bridge);
02050       return props->atxferdropcall ? TRANSFER_BLOND : TRANSFER_BLOND_NONFINAL;
02051    case STIMULUS_TRANSFER_TARGET_ANSWER:
02052       return TRANSFER_CONSULTING;
02053    case STIMULUS_TRANSFER_TARGET_HANGUP:
02054    case STIMULUS_TIMEOUT:
02055    case STIMULUS_DTMF_ATXFER_ABORT:
02056       play_sound(props->transferer, props->failsound);
02057       return TRANSFER_REBRIDGE;
02058    case STIMULUS_DTMF_ATXFER_THREEWAY:
02059       bridge_unhold(props->transferee_bridge);
02060       return TRANSFER_THREEWAY;
02061    case STIMULUS_DTMF_ATXFER_SWAP:
02062       return TRANSFER_HESITANT;
02063    case STIMULUS_NONE:
02064    case STIMULUS_RECALL_TARGET_ANSWER:
02065    case STIMULUS_RECALL_TARGET_HANGUP:
02066    default:
02067       ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
02068             stimulus_strs[stimulus], state_properties[props->state].state_name);
02069       return props->state;
02070    }
02071 }

static void clear_stimulus_queue ( struct attended_transfer_properties props  )  [static]

Free backlog of stimuli in the queue.

Definition at line 1488 of file bridge_basic.c.

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

Referenced by attended_transfer_properties_shutdown().

01489 {
01490    struct stimulus_list *list;
01491    SCOPED_AO2LOCK(lock, props);
01492 
01493    while ((list = AST_LIST_REMOVE_HEAD(&props->stimulus_queue, next))) {
01494       ast_free(list);
01495    }
01496 }

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

Definition at line 2368 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().

02369 {
02370    ast_callid callid;
02371 
02372    callid = ast_read_threadstorage_callid();
02373    if (callid) {
02374       ast_channel_callid_set(recall, callid);
02375    }
02376 
02377    ast_channel_inherit_variables(transferer, recall);
02378    ast_channel_datastore_inherit(transferer, recall);
02379 
02380    /*
02381     * Stage a snapshot to ensure that a snapshot is always done
02382     * on the recall channel so earler COLP and CLID setup will
02383     * get published.
02384     */
02385    ast_channel_stage_snapshot(recall);
02386    ast_channel_req_accountcodes(recall, transferer, AST_CHANNEL_REQUESTOR_REPLACEMENT);
02387    ast_channel_stage_snapshot_done(recall);
02388 }

static int complete_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2245 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.

02246 {
02247    struct ast_channel *transferee_channel;
02248    struct ast_channel *target_channel;
02249 
02250    get_transfer_parties(props->transferer, props->transferee_bridge, props->target_bridge,
02251          &transferee_channel, &target_channel);
02252    bridge_merge(props->transferee_bridge, props->target_bridge, &props->transferer, 1);
02253    play_sound(props->transfer_target, props->xfersound);
02254    publish_transfer_success(props, transferee_channel, target_channel);
02255 
02256    ast_channel_cleanup(transferee_channel);
02257    ast_channel_cleanup(target_channel);
02258    return 0;
02259 }

static int consulting_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2149 of file bridge_basic.c.

02150 {
02151    return 0;
02152 }

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

Definition at line 2154 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(), attended_transfer_properties::failsound, hold(), LOG_WARNING, NULL, play_sound(), 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_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().

02156 {
02157    switch (stimulus) {
02158    case STIMULUS_TRANSFEREE_HANGUP:
02159       /* This is a one-of-a-kind event. The transferer and transfer target are talking in
02160        * one bridge, and the transferee has hung up in a separate bridge. In this case, we
02161        * will change the personality of the transfer target bridge back to normal, and play
02162        * a sound to the transferer to indicate the transferee is gone.
02163        */
02164       bridge_basic_change_personality(props->target_bridge, BRIDGE_BASIC_PERSONALITY_NORMAL, NULL);
02165       play_sound(props->transferer, props->failsound);
02166       ast_bridge_merge_inhibit(props->target_bridge, -1);
02167       /* These next two lines are here to ensure that our reference to the target bridge
02168        * is cleaned up properly and that the target bridge is not destroyed when the
02169        * monitor thread exits
02170        */
02171       ao2_ref(props->target_bridge, -1);
02172       props->target_bridge = NULL;
02173       return TRANSFER_FAIL;
02174    case STIMULUS_TRANSFERER_HANGUP:
02175    case STIMULUS_DTMF_ATXFER_COMPLETE:
02176       /* We know the transferer is in the target_bridge, so take the other bridge off hold */
02177       bridge_unhold(props->transferee_bridge);
02178       return TRANSFER_COMPLETE;
02179    case STIMULUS_TRANSFER_TARGET_HANGUP:
02180    case STIMULUS_DTMF_ATXFER_ABORT:
02181       play_sound(props->transferer, props->failsound);
02182       return TRANSFER_REBRIDGE;
02183    case STIMULUS_DTMF_ATXFER_THREEWAY:
02184       bridge_unhold(props->transferee_bridge);
02185       return TRANSFER_THREEWAY;
02186    case STIMULUS_DTMF_ATXFER_SWAP:
02187       hold(props->transferer);
02188       bridge_move(props->transferee_bridge, props->target_bridge, props->transferer, NULL);
02189       unhold(props->transferer);
02190       return TRANSFER_DOUBLECHECKING;
02191    case STIMULUS_NONE:
02192    case STIMULUS_TIMEOUT:
02193    case STIMULUS_TRANSFER_TARGET_ANSWER:
02194    case STIMULUS_RECALL_TARGET_HANGUP:
02195    case STIMULUS_RECALL_TARGET_ANSWER:
02196    default:
02197       ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
02198             stimulus_strs[stimulus], state_properties[props->state].state_name);
02199       return props->state;
02200    }
02201 }

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

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

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

Definition at line 3178 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().

03179 {
03180    struct ast_channel *chan;
03181    int cause;
03182 
03183    /* Now we request a local channel to prepare to call the destination */
03184    chan = ast_request("Local", ast_channel_nativeformats(caller), NULL, caller, destination,
03185       &cause);
03186    if (!chan) {
03187       return NULL;
03188    }
03189 
03190    ast_channel_lock_both(chan, caller);
03191 
03192    ast_channel_req_accountcodes(chan, caller, AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
03193 
03194    /* Who is transferring the call. */
03195    pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", ast_channel_name(caller));
03196 
03197    ast_bridge_set_transfer_variables(chan, ast_channel_name(caller), 1);
03198 
03199    ast_channel_unlock(chan);
03200    ast_channel_unlock(caller);
03201 
03202    /* Before we actually dial out let's inherit appropriate information. */
03203    copy_caller_data(chan, caller);
03204 
03205    return chan;
03206 }

static int double_checking_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2203 of file bridge_basic.c.

02204 {
02205    return 0;
02206 }

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

Definition at line 2208 of file bridge_basic.c.

References ast_log, bridge_move(), bridge_unhold(), attended_transfer_properties::failsound, hold(), LOG_WARNING, NULL, play_sound(), 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_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().

02210 {
02211    switch (stimulus) {
02212    case STIMULUS_TRANSFEREE_HANGUP:
02213       play_sound(props->transferer, props->failsound);
02214       publish_transfer_fail(props);
02215       return TRANSFER_FAIL;
02216    case STIMULUS_TRANSFERER_HANGUP:
02217    case STIMULUS_DTMF_ATXFER_COMPLETE:
02218       /* We know the transferer is in the transferee, so take the other bridge off hold */
02219       bridge_unhold(props->target_bridge);
02220       return TRANSFER_COMPLETE;
02221    case STIMULUS_TRANSFER_TARGET_HANGUP:
02222    case STIMULUS_DTMF_ATXFER_ABORT:
02223       play_sound(props->transferer, props->failsound);
02224       return TRANSFER_RESUME;
02225    case STIMULUS_DTMF_ATXFER_THREEWAY:
02226       bridge_unhold(props->target_bridge);
02227       return TRANSFER_THREEWAY;
02228    case STIMULUS_DTMF_ATXFER_SWAP:
02229       hold(props->transferer);
02230       bridge_move(props->target_bridge, props->transferee_bridge, props->transferer, NULL);
02231       unhold(props->transferer);
02232       return TRANSFER_CONSULTING;
02233    case STIMULUS_NONE:
02234    case STIMULUS_TIMEOUT:
02235    case STIMULUS_TRANSFER_TARGET_ANSWER:
02236    case STIMULUS_RECALL_TARGET_HANGUP:
02237    case STIMULUS_RECALL_TARGET_ANSWER:
02238    default:
02239       ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
02240             stimulus_strs[stimulus], state_properties[props->state].state_name);
02241       return props->state;
02242    }
02243 }

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

Definition at line 135 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().

00136 {
00137    size_t buffer_expended = 0;
00138    unsigned int cur_feature;
00139    static const struct {
00140       char letter;
00141       unsigned int flag;
00142    } associations[] = {
00143       { 'T', AST_FEATURE_REDIRECT },
00144       { 'K', AST_FEATURE_PARKCALL },
00145       { 'H', AST_FEATURE_DISCONNECT },
00146       { 'W', AST_FEATURE_AUTOMON },
00147       { 'X', AST_FEATURE_AUTOMIXMON },
00148    };
00149 
00150    for (cur_feature = 0; cur_feature < ARRAY_LEN(associations); cur_feature++) {
00151       if (ast_test_flag(feature_flags, associations[cur_feature].flag)) {
00152          if (buffer_expended == buffer_size - 1) {
00153             buffer[buffer_expended] = '\0';
00154             return -1;
00155          }
00156          buffer[buffer_expended++] = associations[cur_feature].letter;
00157       }
00158    }
00159 
00160    buffer[buffer_expended] = '\0';
00161    return 0;
00162 }

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

00547 {
00548    struct dynamic_dtmf_hook_data *hook_data;
00549    size_t len_name = strlen(app_name) + 1;
00550    size_t len_args = ast_strlen_zero(app_args) ? 0 : strlen(app_args) + 1;
00551    size_t len_moh = ast_strlen_zero(moh_class) ? 0 : strlen(moh_class) + 1;
00552    size_t len_feature = strlen(feature_name) + 1;
00553    size_t len_data = sizeof(*hook_data) + len_name + len_args + len_moh + len_feature;
00554    int res;
00555 
00556    /* Fill in application run hook data. */
00557    hook_data = ast_malloc(len_data);
00558    if (!hook_data) {
00559       return -1;
00560    }
00561    hook_data->flags = flags;
00562    hook_data->app_args_offset = len_args ? len_name : 0;
00563    hook_data->moh_offset = len_moh ? len_name + len_args : 0;
00564    hook_data->feature_offset = len_name + len_args + len_moh;
00565    strcpy(hook_data->app_name, app_name);/* Safe */
00566    if (len_args) {
00567       strcpy(&hook_data->app_name[hook_data->app_args_offset], app_args);/* Safe */
00568    }
00569    if (len_moh) {
00570       strcpy(&hook_data->app_name[hook_data->moh_offset], moh_class);/* Safe */
00571    }
00572    strcpy(&hook_data->app_name[hook_data->feature_offset], feature_name);/* Safe */
00573 
00574    res = ast_bridge_dtmf_hook(features, dtmf, dynamic_dtmf_hook_trip, hook_data,
00575       ast_free_ptr,
00576       AST_BRIDGE_HOOK_REMOVE_ON_PULL | AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE);
00577    if (res) {
00578       ast_free(hook_data);
00579    }
00580    return res;
00581 }

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

Definition at line 438 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().

00440 {
00441    struct ast_channel *chan = bridge_channel->chan;
00442    const struct dynamic_dtmf_hook_run *run_data = payload;
00443 
00444    pbx_builtin_setvar_helper(chan, "DYNAMIC_FEATURENAME",
00445       &run_data->app_name[run_data->feature_offset]);
00446    pbx_builtin_setvar_helper(chan, "DYNAMIC_WHO_ACTIVATED",
00447       &run_data->app_name[run_data->activated_offset]);
00448 
00449    ast_bridge_channel_run_app(bridge_channel, run_data->app_name,
00450       run_data->app_args_offset ? &run_data->app_name[run_data->app_args_offset] : NULL,
00451       run_data->moh_offset ? &run_data->app_name[run_data->moh_offset] : NULL);
00452 }

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

Definition at line 478 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().

00479 {
00480    struct dynamic_dtmf_hook_data *pvt = hook_pvt;
00481    struct dynamic_dtmf_hook_run *run_data;
00482    const char *activated_name;
00483    size_t len_name;
00484    size_t len_args;
00485    size_t len_moh;
00486    size_t len_feature;
00487    size_t len_activated;
00488    size_t len_data;
00489 
00490    /* Determine lengths of things. */
00491    len_name = strlen(pvt->app_name) + 1;
00492    len_args = pvt->app_args_offset ? strlen(&pvt->app_name[pvt->app_args_offset]) + 1 : 0;
00493    len_moh = pvt->moh_offset ? strlen(&pvt->app_name[pvt->moh_offset]) + 1 : 0;
00494    len_feature = strlen(&pvt->app_name[pvt->feature_offset]) + 1;
00495    ast_channel_lock(bridge_channel->chan);
00496    activated_name = ast_strdupa(ast_channel_name(bridge_channel->chan));
00497    ast_channel_unlock(bridge_channel->chan);
00498    len_activated = strlen(activated_name) + 1;
00499    len_data = sizeof(*run_data) + len_name + len_args + len_moh + len_feature + len_activated;
00500 
00501    /* Fill in dynamic feature run hook data. */
00502    run_data = ast_alloca(len_data);
00503    run_data->app_args_offset = len_args ? len_name : 0;
00504    run_data->moh_offset = len_moh ? len_name + len_args : 0;
00505    run_data->feature_offset = len_name + len_args + len_moh;
00506    run_data->activated_offset = len_name + len_args + len_moh + len_feature;
00507    strcpy(run_data->app_name, pvt->app_name);/* Safe */
00508    if (len_args) {
00509       strcpy(&run_data->app_name[run_data->app_args_offset],
00510          &pvt->app_name[pvt->app_args_offset]);/* Safe */
00511    }
00512    if (len_moh) {
00513       strcpy(&run_data->app_name[run_data->moh_offset],
00514          &pvt->app_name[pvt->moh_offset]);/* Safe */
00515    }
00516    strcpy(&run_data->app_name[run_data->feature_offset],
00517       &pvt->app_name[pvt->feature_offset]);/* Safe */
00518    strcpy(&run_data->app_name[run_data->activated_offset], activated_name);/* Safe */
00519 
00520    if (ast_test_flag(pvt, AST_FEATURE_FLAG_ONPEER)) {
00521       ast_bridge_channel_write_callback(bridge_channel,
00522          AST_BRIDGE_CHANNEL_CB_OPTION_MEDIA,
00523          dynamic_dtmf_hook_callback, run_data, len_data);
00524    } else {
00525       dynamic_dtmf_hook_callback(bridge_channel, run_data, len_data);
00526    }
00527    return 0;
00528 }

static int fail_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2662 of file bridge_basic.c.

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

02663 {
02664    if (props->transferee_bridge) {
02665       ast_bridge_destroy(props->transferee_bridge, 0);
02666       props->transferee_bridge = NULL;
02667    }
02668    return 0;
02669 }

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_channel The channel that pressed the attended transfer DTMF sequence
hook_pvt Structure with further information about the attended transfer

Definition at line 3218 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_DIGIT_NONE, ast_hangup(), ast_log, AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_pthread_create_detached, ast_stream_and_wait(), 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, attended_transfer_properties::context, ast_bridge_features_attended_transfer::context, dial_transfer(), attended_transfer_properties::exten, exten, attended_transfer_properties::failsound, grab_transfer(), ast_bridge::inhibit_merge, LOG_ERROR, LOG_WARNING, ast_bridge_methods::name, NULL, 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().

03219 {
03220    struct ast_bridge_features_attended_transfer *attended_transfer = hook_pvt;
03221    struct attended_transfer_properties *props;
03222    struct ast_bridge *bridge;
03223    char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
03224    char exten[AST_MAX_EXTENSION] = "";
03225    pthread_t thread;
03226 
03227    /* Inhibit the bridge before we do anything else. */
03228    bridge = ast_bridge_channel_merge_inhibit(bridge_channel, +1);
03229 
03230    if (strcmp(bridge->v_table->name, "basic")) {
03231       ast_log(LOG_ERROR, "Attended transfer attempted on unsupported bridge type '%s'.\n",
03232          bridge->v_table->name);
03233       ast_bridge_merge_inhibit(bridge, -1);
03234       ao2_ref(bridge, -1);
03235       return 0;
03236    }
03237 
03238    /* Was the bridge inhibited before we inhibited it? */
03239    if (1 < bridge->inhibit_merge) {
03240       /*
03241        * The peer likely initiated attended transfer at the same time
03242        * and we lost the race.
03243        */
03244       ast_verb(3, "Channel %s: Bridge '%s' does not permit merging at this time.\n",
03245          ast_channel_name(bridge_channel->chan), bridge->uniqueid);
03246       ast_bridge_merge_inhibit(bridge, -1);
03247       ao2_ref(bridge, -1);
03248       return 0;
03249    }
03250 
03251    props = attended_transfer_properties_alloc(bridge_channel->chan,
03252       attended_transfer ? attended_transfer->context : NULL);
03253    if (!props) {
03254       ast_log(LOG_ERROR, "Unable to allocate control structure for performing attended transfer.\n");
03255       ast_bridge_merge_inhibit(bridge, -1);
03256       ao2_ref(bridge, -1);
03257       return 0;
03258    }
03259 
03260    props->transferee_bridge = bridge;
03261 
03262    if (add_transferer_role(props->transferer, attended_transfer)) {
03263       ast_log(LOG_ERROR, "Unable to set transferrer bridge role.\n");
03264       attended_transfer_properties_shutdown(props);
03265       return 0;
03266    }
03267 
03268    ast_bridge_channel_write_hold(bridge_channel, NULL);
03269 
03270    /* Grab the extension to transfer to */
03271    if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), props->context)) {
03272       ast_log(LOG_WARNING, "Unable to acquire target extension for attended transfer.\n");
03273       ast_bridge_channel_write_unhold(bridge_channel);
03274       attended_transfer_properties_shutdown(props);
03275       return 0;
03276    }
03277 
03278    ast_string_field_set(props, exten, exten);
03279 
03280    /* Fill the variable with the extension and context we want to call */
03281    snprintf(destination, sizeof(destination), "%s@%s", props->exten, props->context);
03282 
03283    ast_debug(1, "Attended transfer to '%s'\n", destination);
03284 
03285    /* Get a channel that is the destination we wish to call */
03286    props->transfer_target = dial_transfer(bridge_channel->chan, destination);
03287    if (!props->transfer_target) {
03288       ast_log(LOG_ERROR, "Unable to request outbound channel for attended transfer target.\n");
03289       ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
03290       ast_bridge_channel_write_unhold(bridge_channel);
03291       attended_transfer_properties_shutdown(props);
03292       return 0;
03293    }
03294 
03295 
03296    /* Create a bridge to use to talk to the person we are calling */
03297    props->target_bridge = ast_bridge_basic_new();
03298    if (!props->target_bridge) {
03299       ast_log(LOG_ERROR, "Unable to create bridge for attended transfer target.\n");
03300       ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
03301       ast_bridge_channel_write_unhold(bridge_channel);
03302       ast_hangup(props->transfer_target);
03303       props->transfer_target = NULL;
03304       attended_transfer_properties_shutdown(props);
03305       return 0;
03306    }
03307    ast_bridge_merge_inhibit(props->target_bridge, +1);
03308 
03309    if (attach_framehook(props, props->transfer_target)) {
03310       ast_log(LOG_ERROR, "Unable to attach framehook to transfer target.\n");
03311       ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
03312       ast_bridge_channel_write_unhold(bridge_channel);
03313       ast_hangup(props->transfer_target);
03314       props->transfer_target = NULL;
03315       attended_transfer_properties_shutdown(props);
03316       return 0;
03317    }
03318 
03319    bridge_basic_change_personality(props->target_bridge,
03320          BRIDGE_BASIC_PERSONALITY_ATXFER, props);
03321    bridge_basic_change_personality(bridge,
03322          BRIDGE_BASIC_PERSONALITY_ATXFER, props);
03323 
03324    if (ast_call(props->transfer_target, destination, 0)) {
03325       ast_log(LOG_ERROR, "Unable to place outbound call to transfer target.\n");
03326       ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
03327       ast_bridge_channel_write_unhold(bridge_channel);
03328       ast_hangup(props->transfer_target);
03329       props->transfer_target = NULL;
03330       attended_transfer_properties_shutdown(props);
03331       return 0;
03332    }
03333 
03334    /* We increase the refcount of the transfer target because ast_bridge_impart() will
03335     * steal the reference we already have. We need to keep a reference, so the only
03336     * choice is to give it a bump
03337     */
03338    ast_channel_ref(props->transfer_target);
03339    if (ast_bridge_impart(props->target_bridge, props->transfer_target, NULL, NULL,
03340       AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
03341       ast_log(LOG_ERROR, "Unable to place transfer target into bridge.\n");
03342       ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
03343       ast_bridge_channel_write_unhold(bridge_channel);
03344       ast_hangup(props->transfer_target);
03345       props->transfer_target = NULL;
03346       attended_transfer_properties_shutdown(props);
03347       return 0;
03348    }
03349 
03350    if (ast_pthread_create_detached(&thread, NULL, attended_transfer_monitor_thread, props)) {
03351       ast_log(LOG_ERROR, "Unable to create monitoring thread for attended transfer.\n");
03352       ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
03353       ast_bridge_channel_write_unhold(bridge_channel);
03354       attended_transfer_properties_shutdown(props);
03355       return 0;
03356    }
03357 
03358    /* Once the monitoring thread has been created, it is responsible for destroying all
03359     * of the necessary components.
03360     */
03361    return 0;
03362 }

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 3375 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_lock, ast_channel_name(), ast_channel_unlock, ast_debug, AST_MAX_EXTENSION, ast_strdupa, ast_strlen_zero, blind_transfer_cb(), ast_bridge_channel::chan, ast_bridge_features_blind_transfer::context, context, exten, get_transfer_context(), grab_transfer(), NULL, pbx_builtin_getvar_helper(), and S_OR.

Referenced by ast_bridging_init_basic().

03376 {
03377    char exten[AST_MAX_EXTENSION] = "";
03378    struct ast_bridge_features_blind_transfer *blind_transfer = hook_pvt;
03379    const char *context;
03380    char *goto_on_blindxfr;
03381 
03382    ast_bridge_channel_write_hold(bridge_channel, NULL);
03383 
03384    ast_channel_lock(bridge_channel->chan);
03385    context = ast_strdupa(get_transfer_context(bridge_channel->chan,
03386       blind_transfer ? blind_transfer->context : NULL));
03387    goto_on_blindxfr = ast_strdupa(S_OR(pbx_builtin_getvar_helper(bridge_channel->chan,
03388       "GOTO_ON_BLINDXFR"), ""));
03389    ast_channel_unlock(bridge_channel->chan);
03390 
03391    /* Grab the extension to transfer to */
03392    if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
03393       ast_bridge_channel_write_unhold(bridge_channel);
03394       return 0;
03395    }
03396 
03397    if (!ast_strlen_zero(goto_on_blindxfr)) {
03398       ast_debug(1, "After transfer, transferer %s goes to %s\n",
03399             ast_channel_name(bridge_channel->chan), goto_on_blindxfr);
03400       ast_bridge_set_after_go_on(bridge_channel->chan, NULL, NULL, 0, goto_on_blindxfr);
03401    }
03402 
03403    if (ast_bridge_transfer_blind(0, bridge_channel->chan, exten, context, blind_transfer_cb,
03404          bridge_channel->chan) != AST_BRIDGE_TRANSFER_SUCCESS &&
03405          !ast_strlen_zero(goto_on_blindxfr)) {
03406       ast_bridge_discard_after_goto(bridge_channel->chan);
03407    }
03408 
03409    return 0;
03410 }

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

Definition at line 1385 of file bridge_basic.c.

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

Referenced by attended_transfer_properties_alloc(), and feature_blind_transfer().

01386 {
01387    if (!ast_strlen_zero(context)) {
01388       return context;
01389    }
01390    context = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
01391    if (!ast_strlen_zero(context)) {
01392       return context;
01393    }
01394    context = ast_channel_macrocontext(transferer);
01395    if (!ast_strlen_zero(context)) {
01396       return context;
01397    }
01398    context = ast_channel_context(transferer);
01399    if (!ast_strlen_zero(context)) {
01400       return context;
01401    }
01402    return "default";
01403 }

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:
transferer The channel performing the transfer
transferee_bridge The bridge that the transferee is in
target_bridge The bridge that the transfer target is in
[out] transferee The transferee channel
[out] transfer_target The transfer target channel

Definition at line 1597 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().

01600 {
01601    struct ast_bridge *transferer_bridge;
01602 
01603    ast_channel_lock(transferer);
01604    transferer_bridge = ast_channel_get_bridge(transferer);
01605    ast_channel_unlock(transferer);
01606 
01607    if (transferer_bridge == transferee_bridge) {
01608       get_transfer_parties_transferer_bridge(transferee_bridge, target_bridge,
01609             transferer, transferee, transfer_target);
01610    } else if (transferer_bridge == target_bridge) {
01611       get_transfer_parties_transferer_bridge(target_bridge, transferee_bridge,
01612             transferer, transfer_target, transferee);
01613    } else {
01614       get_transfer_party_non_transferer_bridge(transferee_bridge, transferee);
01615       get_transfer_party_non_transferer_bridge(target_bridge, transfer_target);
01616    }
01617 
01618    ao2_cleanup(transferer_bridge);
01619 }

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_bridge The bridge the transferer is in
other_bridge The bridge the transferer is not in. May be NULL.
transferer The transferer party
[out] transferer_peer The party that is in the bridge with the transferer
[out] other_party The party that is in the other_bridge

Definition at line 1572 of file bridge_basic.c.

References ast_bridge_peer(), and get_transfer_party_non_transferer_bridge().

Referenced by get_transfer_parties().

01575 {
01576    *transferer_peer = ast_bridge_peer(transferer_bridge, transferer);
01577    get_transfer_party_non_transferer_bridge(other_bridge, other_party);
01578 }

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:
bridge The bridge to get the party from. May be NULL.
[out] party The lone channel in the bridge. Will be set NULL if bridge is NULL or multiple parties are present.

Definition at line 1552 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().

01554 {
01555    if (bridge && bridge->num_channels == 1) {
01556       *party = ast_channel_ref(AST_LIST_FIRST(&bridge->channels)->chan);
01557    } else {
01558       *party = NULL;
01559    }
01560 }

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:
0 on success
-1 on failure

Definition at line 3085 of file bridge_basic.c.

References ao2_cleanup, ast_app_dtget(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, 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, LOG_ERROR, NULL, and RAII_VAR.

Referenced by feature_attended_transfer(), and feature_blind_transfer().

03086 {
03087    int res;
03088    int digit_timeout;
03089    int attempts = 0;
03090    int max_attempts;
03091    RAII_VAR(struct ast_features_xfer_config *, xfer_cfg, NULL, ao2_cleanup);
03092    char *retry_sound;
03093    char *invalid_sound;
03094 
03095    ast_channel_lock(chan);
03096    xfer_cfg = ast_get_chan_features_xfer_config(chan);
03097    if (!xfer_cfg) {
03098       ast_log(LOG_ERROR, "Unable to get transfer configuration\n");
03099       ast_channel_unlock(chan);
03100       return -1;
03101    }
03102    digit_timeout = xfer_cfg->transferdigittimeout * 1000;
03103    max_attempts = xfer_cfg->transferdialattempts;
03104    retry_sound = ast_strdupa(xfer_cfg->transferretrysound);
03105    invalid_sound = ast_strdupa(xfer_cfg->transferinvalidsound);
03106    ast_channel_unlock(chan);
03107 
03108    /* Play the simple "transfer" prompt out and wait */
03109    res = ast_stream_and_wait(chan, "pbx-transfer", AST_DIGIT_ANY);
03110    ast_stopstream(chan);
03111    if (res < 0) {
03112       /* Hangup or error */
03113       return -1;
03114    }
03115    if (res) {
03116       /* Store the DTMF digit that interrupted playback of the file. */
03117       exten[0] = res;
03118    }
03119 
03120    /* Drop to dialtone so they can enter the extension they want to transfer to */
03121    do {
03122       ++attempts;
03123 
03124       ast_test_suite_event_notify("TRANSFER_BEGIN_DIAL",
03125             "Channel: %s\r\n"
03126             "Attempt: %d",
03127             ast_channel_name(chan), attempts);
03128       res = ast_app_dtget(chan, context, exten, exten_len, exten_len - 1, digit_timeout);
03129       ast_test_suite_event_notify("TRANSFER_DIALLED",
03130             "Channel: %s\r\n"
03131             "Attempt: %d\r\n"
03132             "Dialled: %s\r\n"
03133             "Result: %s",
03134             ast_channel_name(chan), attempts, exten, res > 0 ? "Success" : "Failure");
03135       if (res < 0) {
03136          /* Hangup or error */
03137          res = -1;
03138       } else if (!res) {
03139          /* 0 for invalid extension dialed. */
03140          if (ast_strlen_zero(exten)) {
03141             ast_debug(1, "%s dialed no digits.\n", ast_channel_name(chan));
03142          } else {
03143             ast_debug(1, "%s dialed '%s@%s' does not exist.\n",
03144                ast_channel_name(chan), exten, context);
03145          }
03146          if (attempts < max_attempts) {
03147             ast_stream_and_wait(chan, retry_sound, AST_DIGIT_NONE);
03148          } else {
03149             ast_stream_and_wait(chan, invalid_sound, AST_DIGIT_NONE);
03150          }
03151          memset(exten, 0, exten_len);
03152          res = 1;
03153       } else {
03154          /* Dialed extension is valid. */
03155          res = 0;
03156       }
03157    } while (res > 0 && attempts < max_attempts);
03158 
03159    ast_test_suite_event_notify("TRANSFER_DIAL_FINAL",
03160          "Channel: %s\r\n"
03161          "Result: %s",
03162          ast_channel_name(chan), res == 0 ? "Success" : "Failure");
03163 
03164    return res ? -1 : 0;
03165 }

static int hesitant_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2073 of file bridge_basic.c.

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

02074 {
02075    if (bridge_move(props->transferee_bridge, props->target_bridge, props->transferer, NULL)) {
02076       return -1;
02077    }
02078 
02079    unhold(props->transferer);
02080    return 0;
02081 }

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

Definition at line 2083 of file bridge_basic.c.

References ast_log, attended_transfer_properties::atxferdropcall, attended_transfer_properties::failsound, hold(), LOG_WARNING, play_sound(), 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_TIMEOUT, STIMULUS_TRANSFER_TARGET_ANSWER, STIMULUS_TRANSFER_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, STIMULUS_TRANSFERER_HANGUP, TRANSFER_BLOND, TRANSFER_BLOND_NONFINAL, TRANSFER_CALLING_TARGET, TRANSFER_DOUBLECHECKING, TRANSFER_FAIL, TRANSFER_RESUME, TRANSFER_THREEWAY, and attended_transfer_properties::transferer.

02085 {
02086    switch (stimulus) {
02087    case STIMULUS_TRANSFEREE_HANGUP:
02088       play_sound(props->transferer, props->failsound);
02089       publish_transfer_fail(props);
02090       return TRANSFER_FAIL;
02091    case STIMULUS_DTMF_ATXFER_COMPLETE:
02092    case STIMULUS_TRANSFERER_HANGUP:
02093       return props->atxferdropcall ? TRANSFER_BLOND : TRANSFER_BLOND_NONFINAL;
02094    case STIMULUS_TRANSFER_TARGET_ANSWER:
02095       return TRANSFER_DOUBLECHECKING;
02096    case STIMULUS_TRANSFER_TARGET_HANGUP:
02097    case STIMULUS_TIMEOUT:
02098    case STIMULUS_DTMF_ATXFER_ABORT:
02099       play_sound(props->transferer, props->failsound);
02100       return TRANSFER_RESUME;
02101    case STIMULUS_DTMF_ATXFER_THREEWAY:
02102       return TRANSFER_THREEWAY;
02103    case STIMULUS_DTMF_ATXFER_SWAP:
02104       hold(props->transferer);
02105       return TRANSFER_CALLING_TARGET;
02106    case STIMULUS_NONE:
02107    case STIMULUS_RECALL_TARGET_HANGUP:
02108    case STIMULUS_RECALL_TARGET_ANSWER:
02109    default:
02110       ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
02111             stimulus_strs[stimulus], state_properties[props->state].state_name);
02112       return props->state;
02113    }
02114 }

static void hold ( struct ast_channel chan  )  [static]

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

Definition at line 1714 of file bridge_basic.c.

References ao2_cleanup, ast_assert, ast_bridge_channel_write_hold(), ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, NULL, and RAII_VAR.

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

01715 {
01716    RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
01717 
01718    if (chan) {
01719       ast_channel_lock(chan);
01720       bridge_channel = ast_channel_get_bridge_channel(chan);
01721       ast_channel_unlock(chan);
01722 
01723       ast_assert(bridge_channel != NULL);
01724 
01725       ast_bridge_channel_write_hold(bridge_channel, NULL);
01726    }
01727 }

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

static void on_personality_change_normal ( struct ast_bridge bridge  )  [static]

Definition at line 3449 of file bridge_basic.c.

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

Referenced by init_details().

03450 {
03451    struct ast_bridge_channel *iter;
03452 
03453    AST_LIST_TRAVERSE(&bridge->channels, iter, entry) {
03454       if (add_normal_hooks(bridge, iter)) {
03455          ast_log(LOG_WARNING, "Unable to set up bridge hooks for channel %s. Features may not work properly\n",
03456                ast_channel_name(iter->chan));
03457       }
03458    }
03459 }

static void personality_destructor ( void *  obj  )  [static]

Definition at line 3439 of file bridge_basic.c.

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

Referenced by bridge_basic_personality_alloc().

03440 {
03441    struct bridge_basic_personality *personality = obj;
03442    int i;
03443 
03444    for (i = 0; i < BRIDGE_BASIC_PERSONALITY_END; ++i) {
03445       ao2_cleanup(personality->details[i].pvt);
03446    }
03447 }

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

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

Parameters:
chan The channel to play the sound to
sound The sound to play

Definition at line 1696 of file bridge_basic.c.

References ao2_cleanup, ast_bridge_channel_queue_playfile(), ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, NULL, and RAII_VAR.

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

01697 {
01698    RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
01699 
01700    ast_channel_lock(chan);
01701    bridge_channel = ast_channel_get_bridge_channel(chan);
01702    ast_channel_unlock(chan);
01703 
01704    if (!bridge_channel) {
01705       return;
01706    }
01707 
01708    ast_bridge_channel_queue_playfile(bridge_channel, NULL, sound, NULL);
01709 }

static void publish_transfer_fail ( struct attended_transfer_properties props  )  [static]

Send a stasis publication for a failed attended transfer.

Definition at line 1671 of file bridge_basic.c.

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

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

01672 {
01673    struct ast_attended_transfer_message *transfer_msg;
01674 
01675    transfer_msg = ast_attended_transfer_message_create(0, props->transferer,
01676          props->transferee_bridge, props->transferer, props->target_bridge,
01677          NULL, NULL);
01678 
01679    if (!transfer_msg) {
01680       ast_log(LOG_ERROR, "Unable to publish failed transfer from %s\n",
01681             ast_channel_name(props->transferer));
01682       return;
01683    }
01684 
01685    transfer_msg->result = AST_BRIDGE_TRANSFER_FAIL;
01686    ast_bridge_publish_attended_transfer(transfer_msg);
01687    ao2_cleanup(transfer_msg);
01688 }

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

Send a stasis publication for a successful attended transfer.

Definition at line 1624 of file bridge_basic.c.

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

Referenced by blond_enter(), and complete_enter().

01626 {
01627    struct ast_attended_transfer_message *transfer_msg;
01628 
01629    transfer_msg = ast_attended_transfer_message_create(0, props->transferer,
01630          props->transferee_bridge, props->transferer, props->target_bridge,
01631          transferee_channel, target_channel);
01632 
01633    if (!transfer_msg) {
01634       ast_log(LOG_ERROR, "Unable to publish successful attended transfer from %s\n",
01635             ast_channel_name(props->transferer));
01636       return;
01637    }
01638 
01639    ast_attended_transfer_message_add_merge(transfer_msg, props->transferee_bridge);
01640    ast_bridge_publish_attended_transfer(transfer_msg);
01641    ao2_cleanup(transfer_msg);
01642 }

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

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

Definition at line 1647 of file bridge_basic.c.

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

Referenced by threeway_enter().

01649 {
01650    struct ast_attended_transfer_message *transfer_msg;
01651 
01652    transfer_msg = ast_attended_transfer_message_create(0, props->transferer,
01653          props->transferee_bridge, props->transferer, props->target_bridge,
01654          transferee_channel, target_channel);
01655 
01656    if (!transfer_msg) {
01657       ast_log(LOG_ERROR, "Unable to publish successful three-way transfer from %s\n",
01658             ast_channel_name(props->transferer));
01659       return;
01660    }
01661 
01662    ast_attended_transfer_message_add_threeway(transfer_msg, props->transferer,
01663          props->transferee_bridge);
01664    ast_bridge_publish_attended_transfer(transfer_msg);
01665    ao2_cleanup(transfer_msg);
01666 }

static int rebridge_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2116 of file bridge_basic.c.

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

02117 {
02118    if (bridge_move(props->transferee_bridge, props->target_bridge,
02119          props->transferer, NULL)) {
02120       return -1;
02121    }
02122 
02123    unhold(props->transferer);
02124    return 0;
02125 }

static void recall_callback ( struct ast_dial dial  )  [static]

Dial callback when attempting to recall the original transferer channel.

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

Definition at line 2323 of file bridge_basic.c.

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

Referenced by recalling_enter().

02324 {
02325    struct attended_transfer_properties *props = ast_dial_get_user_data(dial);
02326 
02327    switch (ast_dial_state(dial)) {
02328    default:
02329    case AST_DIAL_RESULT_INVALID:
02330    case AST_DIAL_RESULT_FAILED:
02331    case AST_DIAL_RESULT_TIMEOUT:
02332    case AST_DIAL_RESULT_HANGUP:
02333    case AST_DIAL_RESULT_UNANSWERED:
02334       /* Failure cases */
02335       stimulate_attended_transfer(props, STIMULUS_RECALL_TARGET_HANGUP);
02336       break;
02337    case AST_DIAL_RESULT_RINGING:
02338    case AST_DIAL_RESULT_PROGRESS:
02339    case AST_DIAL_RESULT_PROCEEDING:
02340    case AST_DIAL_RESULT_TRYING:
02341       /* Don't care about these cases */
02342       break;
02343    case AST_DIAL_RESULT_ANSWERED:
02344       /* We struck gold! */
02345       props->recall_target = ast_dial_answered_steal(dial);
02346       stimulate_attended_transfer(props, STIMULUS_RECALL_TARGET_ANSWER);
02347       break;
02348    }
02349 }

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

Definition at line 2870 of file bridge_basic.c.

References ao2_cleanup, ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, AST_LIST_FIRST, ast_bridge_channel::chan, NULL, RAII_VAR, attended_transfer_properties::recall_target, stimulate_attended_transfer(), STIMULUS_RECALL_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, and attended_transfer_properties::target_bridge.

Referenced by bridge_personality_atxfer_pull().

02871 {
02872    if (self == props->target_bridge) {
02873       /* Once we're in the recall superstate, we no longer care about this bridge */
02874       return;
02875    }
02876 
02877    if (bridge_channel->chan == props->recall_target) {
02878       stimulate_attended_transfer(props, STIMULUS_RECALL_TARGET_HANGUP);
02879       return;
02880    }
02881 
02882    if (self->num_channels == 0) {
02883       /* Empty bridge means all transferees are gone for sure */
02884       stimulate_attended_transfer(props, STIMULUS_TRANSFEREE_HANGUP);
02885       return;
02886    }
02887 
02888    if (self->num_channels == 1) {
02889       RAII_VAR(struct ast_bridge_channel *, target_bridge_channel, NULL, ao2_cleanup);
02890       if (!props->recall_target) {
02891          /* No recall target means that the pull happened on a transferee. If there's still
02892           * a channel left in the bridge, we don't need to send a stimulus
02893           */
02894          return;
02895       }
02896 
02897       ast_channel_lock(props->recall_target);
02898       target_bridge_channel = ast_channel_get_bridge_channel(props->recall_target);
02899       ast_channel_unlock(props->recall_target);
02900 
02901       if (!target_bridge_channel) {
02902          return;
02903       }
02904 
02905       if (AST_LIST_FIRST(&self->channels) == target_bridge_channel) {
02906          stimulate_attended_transfer(props, STIMULUS_TRANSFEREE_HANGUP);
02907       }
02908    }
02909 }

static int recalling_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2390 of file bridge_basic.c.

References ao2_cleanup, ao2_ref, ast_channel_caller(), ast_channel_connected(), ast_channel_lock_both, ast_channel_unlock, ast_dial_append(), ast_dial_create(), ast_dial_get_channel(), ast_dial_prerun(), AST_DIAL_RESULT_FAILED, ast_dial_run(), ast_dial_set_state_callback(), ast_dial_set_user_data(), ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_slin, ast_party_caller_copy(), ast_party_connected_line_copy(), bridge_ringing(), common_recall_channel_setup(), attended_transfer_properties::dial, NULL, attended_transfer_properties::original_transferer_colp, RAII_VAR, recall_callback(), attended_transfer_properties::transferee_bridge, attended_transfer_properties::transferer, attended_transfer_properties::transferer_addr, and attended_transfer_properties::transferer_type.

02391 {
02392    RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
02393    struct ast_channel *recall;
02394 
02395    if (!cap) {
02396       return -1;
02397    }
02398 
02399    ast_format_cap_append(cap, ast_format_slin, 0);
02400 
02401    /* When we dial the transfer target, since we are communicating
02402     * with a local channel, we can place the local channel in a bridge
02403     * and then call out to it. When recalling the transferer, though, we
02404     * have to use the dialing API because the channel is not local.
02405     */
02406    props->dial = ast_dial_create();
02407    if (!props->dial) {
02408       return -1;
02409    }
02410 
02411    if (ast_dial_append(props->dial, props->transferer_type, props->transferer_addr, NULL)) {
02412       return -1;
02413    }
02414 
02415    if (ast_dial_prerun(props->dial, NULL, cap)) {
02416       return -1;
02417    }
02418 
02419    /*
02420     * Setup callid, variables, datastores, accountcode, peeraccount,
02421     * COLP, and CLID on the recalled transferrer.
02422     */
02423    recall = ast_dial_get_channel(props->dial, 0);
02424    if (!recall) {
02425       return -1;
02426    }
02427    ast_channel_lock_both(recall, props->transferer);
02428 
02429    ast_party_caller_copy(ast_channel_caller(recall),
02430       ast_channel_caller(props->transferer));
02431    ast_party_connected_line_copy(ast_channel_connected(recall),
02432       &props->original_transferer_colp);
02433 
02434    common_recall_channel_setup(recall, props->transferer);
02435    ast_channel_unlock(recall);
02436    ast_channel_unlock(props->transferer);
02437 
02438    ast_dial_set_state_callback(props->dial, recall_callback);
02439 
02440    ao2_ref(props, +1);
02441    ast_dial_set_user_data(props->dial, props);
02442 
02443    if (ast_dial_run(props->dial, NULL, 1) == AST_DIAL_RESULT_FAILED) {
02444       ao2_ref(props, -1);
02445       return -1;
02446    }
02447 
02448    bridge_ringing(props->transferee_bridge);
02449    return 0;
02450 }

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

Definition at line 2452 of file bridge_basic.c.

References ao2_ref, ast_bridge_features_ds_set(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_channel_ref, ast_channel_unref, ast_dial_destroy(), ast_dial_join(), ast_hangup(), ast_log, attended_transfer_properties::atxfercallbackretries, attended_transfer_properties::atxferloopdelay, attended_transfer_properties::dial, LOG_WARNING, NULL, attended_transfer_properties::recall_target, attended_transfer_properties::retry_attempts, attended_transfer_properties::state, attended_transfer_state_properties::state_name, 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_TIMEOUT, STIMULUS_TRANSFER_TARGET_ANSWER, STIMULUS_TRANSFER_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, STIMULUS_TRANSFERER_HANGUP, TRANSFER_FAIL, TRANSFER_RESUME, TRANSFER_RETRANSFER, TRANSFER_WAIT_TO_RETRANSFER, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer_features.

02454 {
02455    /* No matter what the outcome was, we need to kill off the dial */
02456    ast_dial_join(props->dial);
02457    ast_dial_destroy(props->dial);
02458    props->dial = NULL;
02459    /* This reference is the one we incremented for the dial state callback (recall_callback) to use */
02460    ao2_ref(props, -1);
02461 
02462    switch (stimulus) {
02463    case STIMULUS_TRANSFEREE_HANGUP:
02464       return TRANSFER_FAIL;
02465    case STIMULUS_TIMEOUT:
02466    case STIMULUS_RECALL_TARGET_HANGUP:
02467       ++props->retry_attempts;
02468       if (props->retry_attempts >= props->atxfercallbackretries) {
02469          return TRANSFER_FAIL;
02470       }
02471       if (props->atxferloopdelay) {
02472          return TRANSFER_WAIT_TO_RETRANSFER;
02473       }
02474       return TRANSFER_RETRANSFER;
02475    case STIMULUS_RECALL_TARGET_ANSWER:
02476       /* Setting this datastore up will allow the transferer to have all of his
02477        * call features set up automatically when the bridge changes back to a
02478        * normal personality
02479        */
02480       ast_bridge_features_ds_set(props->recall_target, &props->transferer_features);
02481       ast_channel_ref(props->recall_target);
02482       if (ast_bridge_impart(props->transferee_bridge, props->recall_target, NULL, NULL,
02483          AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
02484          ast_hangup(props->recall_target);
02485          ast_channel_unref(props->recall_target);
02486          return TRANSFER_FAIL;
02487       }
02488       return TRANSFER_RESUME;
02489    case STIMULUS_NONE:
02490    case STIMULUS_DTMF_ATXFER_ABORT:
02491    case STIMULUS_DTMF_ATXFER_COMPLETE:
02492    case STIMULUS_DTMF_ATXFER_THREEWAY:
02493    case STIMULUS_DTMF_ATXFER_SWAP:
02494    case STIMULUS_TRANSFER_TARGET_HANGUP:
02495    case STIMULUS_TRANSFER_TARGET_ANSWER:
02496    case STIMULUS_TRANSFERER_HANGUP:
02497    default:
02498       ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
02499             stimulus_strs[stimulus], state_properties[props->state].state_name);
02500       return props->state;
02501    }
02502 }

static void remove_hooks_on_personality_change ( struct ast_bridge bridge  )  [static]

Remove appropriate hooks when basic bridge personality changes.

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

Parameters:
bridge Basic bridge undergoing personality change

Definition at line 723 of file bridge_basic.c.

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

Referenced by bridge_basic_change_personality().

static int resume_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2127 of file bridge_basic.c.

02128 {
02129    return 0;
02130 }

static int retransfer_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2538 of file bridge_basic.c.

References ao2_cleanup, ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_call(), ast_channel_connected(), ast_channel_lock_both, ast_channel_ref, ast_channel_unlock, ast_channel_unref, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_slin, ast_hangup(), ast_log, AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_party_connected_line_copy(), ast_party_id_reset(), ast_request(), attach_framehook(), common_recall_channel_setup(), attended_transfer_properties::context, attended_transfer_properties::exten, LOG_ERROR, NULL, attended_transfer_properties::original_transferer_colp, ast_party_connected_line::priv, RAII_VAR, attended_transfer_properties::recall_target, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer.

02539 {
02540    RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
02541    char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
02542    int cause;
02543 
02544    if (!cap) {
02545       return -1;
02546    }
02547 
02548    snprintf(destination, sizeof(destination), "%s@%s", props->exten, props->context);
02549 
02550    ast_format_cap_append(cap, ast_format_slin, 0);
02551 
02552    /* Get a channel that is the destination we wish to call */
02553    props->recall_target = ast_request("Local", cap, NULL, NULL, destination, &cause);
02554    if (!props->recall_target) {
02555       ast_log(LOG_ERROR, "Unable to request outbound channel for recall target\n");
02556       return -1;
02557    }
02558 
02559    if (attach_framehook(props, props->recall_target)) {
02560       ast_log(LOG_ERROR, "Unable to attach framehook to recall target\n");
02561       ast_hangup(props->recall_target);
02562       props->recall_target = NULL;
02563       return -1;
02564    }
02565 
02566    /*
02567     * Setup callid, variables, datastores, accountcode, peeraccount,
02568     * and COLP on the recalled transfer target.
02569     */
02570    ast_channel_lock_both(props->recall_target, props->transferer);
02571 
02572    ast_party_connected_line_copy(ast_channel_connected(props->recall_target),
02573       &props->original_transferer_colp);
02574    ast_party_id_reset(&ast_channel_connected(props->recall_target)->priv);
02575 
02576    common_recall_channel_setup(props->recall_target, props->recall_target);
02577    ast_channel_unlock(props->recall_target);
02578    ast_channel_unlock(props->transferer);
02579 
02580    if (ast_call(props->recall_target, destination, 0)) {
02581       ast_log(LOG_ERROR, "Unable to place outbound call to recall target\n");
02582       ast_hangup(props->recall_target);
02583       props->recall_target = NULL;
02584       return -1;
02585    }
02586 
02587    ast_channel_ref(props->recall_target);
02588    if (ast_bridge_impart(props->transferee_bridge, props->recall_target, NULL, NULL,
02589       AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
02590       ast_log(LOG_ERROR, "Unable to place recall target into bridge\n");
02591       ast_hangup(props->recall_target);
02592       ast_channel_unref(props->recall_target);
02593       return -1;
02594    }
02595 
02596    return 0;
02597 }

static enum attended_transfer_state retransfer_exit ( struct attended_transfer_properties props,
enum attended_transfer_stimulus  stimulus 
) [static]

Definition at line 2599 of file bridge_basic.c.

References ast_channel_unref, ast_log, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, attended_transfer_properties::atxferloopdelay, LOG_WARNING, attended_transfer_properties::recall_target, 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_TIMEOUT, STIMULUS_TRANSFER_TARGET_ANSWER, STIMULUS_TRANSFER_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, STIMULUS_TRANSFERER_HANGUP, TRANSFER_FAIL, TRANSFER_RECALLING, TRANSFER_RESUME, and TRANSFER_WAIT_TO_RECALL.

02601 {
02602    switch (stimulus) {
02603    case STIMULUS_TRANSFEREE_HANGUP:
02604       return TRANSFER_FAIL;
02605    case STIMULUS_TIMEOUT:
02606       ast_softhangup(props->recall_target, AST_SOFTHANGUP_EXPLICIT);
02607    case STIMULUS_RECALL_TARGET_HANGUP:
02608       props->recall_target = ast_channel_unref(props->recall_target);
02609       if (props->atxferloopdelay) {
02610          return TRANSFER_WAIT_TO_RECALL;
02611       }
02612       return TRANSFER_RECALLING;
02613    case STIMULUS_RECALL_TARGET_ANSWER:
02614       return TRANSFER_RESUME;
02615    case STIMULUS_NONE:
02616    case STIMULUS_DTMF_ATXFER_ABORT:
02617    case STIMULUS_DTMF_ATXFER_COMPLETE:
02618    case STIMULUS_DTMF_ATXFER_THREEWAY:
02619    case STIMULUS_DTMF_ATXFER_SWAP:
02620    case STIMULUS_TRANSFER_TARGET_HANGUP:
02621    case STIMULUS_TRANSFER_TARGET_ANSWER:
02622    case STIMULUS_TRANSFERER_HANGUP:
02623    default:
02624       ast_log(LOG_WARNING, "Unexpected stimulus '%s' received in attended transfer state '%s'\n",
02625             stimulus_strs[stimulus], state_properties[props->state].state_name);
02626       return props->state;
02627    }
02628 }

static void ringing ( struct ast_channel chan  )  [static]

Helper method to send a ringing indication to a channel in a bridge.

Definition at line 1748 of file bridge_basic.c.

References ao2_cleanup, ast_assert, ast_bridge_channel_write_control_data(), ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_RINGING, NULL, and RAII_VAR.

Referenced by blond_enter(), extensionstate_update(), handle_request_subscribe(), queue_exec(), and update_call_counter().

01749 {
01750    RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
01751 
01752    ast_channel_lock(chan);
01753    bridge_channel = ast_channel_get_bridge_channel(chan);
01754    ast_channel_unlock(chan);
01755 
01756    ast_assert(bridge_channel != NULL);
01757 
01758    ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_RINGING, NULL, 0);
01759 }

static int set_feature_flag_from_char ( struct ast_flags feature_flags,
char  feature 
) [static]

Definition at line 100 of file bridge_basic.c.

References AST_FEATURE_AUTOMIXMON, AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, and ast_set_flag.

Referenced by build_dtmf_features().

00101 {
00102    switch (feature) {
00103    case 'T':
00104       ast_set_flag(feature_flags, AST_FEATURE_REDIRECT);
00105       return 0;
00106    case 'K':
00107       ast_set_flag(feature_flags, AST_FEATURE_PARKCALL);
00108       return 0;
00109    case 'H':
00110       ast_set_flag(feature_flags, AST_FEATURE_DISCONNECT);
00111       return 0;
00112    case 'W':
00113       ast_set_flag(feature_flags, AST_FEATURE_AUTOMON);
00114       return 0;
00115    case 'X':
00116       ast_set_flag(feature_flags, AST_FEATURE_AUTOMIXMON);
00117       return 0;
00118    default:
00119       return -1;
00120    }
00121 }

static int setup_bridge_features_builtin ( struct ast_bridge_features features,
struct ast_channel chan 
) [static]

Definition at line 402 of file bridge_basic.c.

References AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, AST_BRIDGE_BUILTIN_AUTOMIXMON, AST_BRIDGE_BUILTIN_AUTOMON, AST_BRIDGE_BUILTIN_BLINDTRANSFER, AST_BRIDGE_BUILTIN_HANGUP, AST_BRIDGE_BUILTIN_PARKCALL, ast_bridge_features_ds_get(), ast_channel_lock, ast_channel_unlock, AST_FEATURE_AUTOMIXMON, AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, builtin_features_helper(), and ast_flags::flags.

Referenced by bridge_basic_setup_features().

00403 {
00404    struct ast_flags *flags;
00405    int res;
00406 
00407    ast_channel_lock(chan);
00408    flags = ast_bridge_features_ds_get(chan);
00409    ast_channel_unlock(chan);
00410    if (!flags) {
00411       return 0;
00412    }
00413 
00414    res = 0;
00415    res |= builtin_features_helper(features, chan, flags, AST_FEATURE_REDIRECT, "blindxfer", AST_BRIDGE_BUILTIN_BLINDTRANSFER);
00416    res |= builtin_features_helper(features, chan, flags, AST_FEATURE_REDIRECT, "atxfer", AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER);
00417    res |= builtin_features_helper(features, chan, flags, AST_FEATURE_DISCONNECT, "disconnect", AST_BRIDGE_BUILTIN_HANGUP);
00418    res |= builtin_features_helper(features, chan, flags, AST_FEATURE_PARKCALL, "parkcall", AST_BRIDGE_BUILTIN_PARKCALL);
00419    res |= builtin_features_helper(features, chan, flags, AST_FEATURE_AUTOMON, "automon", AST_BRIDGE_BUILTIN_AUTOMON);
00420    res |= builtin_features_helper(features, chan, flags, AST_FEATURE_AUTOMIXMON, "automixmon", AST_BRIDGE_BUILTIN_AUTOMIXMON);
00421 
00422    return res ? -1 : 0;
00423 }

static int setup_bridge_features_dynamic ( struct ast_bridge_features features,
struct ast_channel chan 
) [static]

Definition at line 607 of file bridge_basic.c.

References ao2_callback_data, ao2_cleanup, ast_channel_lock, ast_channel_unlock, ast_get_chan_applicationmap(), NULL, RAII_VAR, and setup_dynamic_feature().

Referenced by bridge_basic_setup_features().

00608 {
00609    RAII_VAR(struct ao2_container *, applicationmap, NULL, ao2_cleanup);
00610    int res = 0;
00611 
00612    ast_channel_lock(chan);
00613    applicationmap = ast_get_chan_applicationmap(chan);
00614    ast_channel_unlock(chan);
00615    if (!applicationmap) {
00616       return 0;
00617    }
00618 
00619    ao2_callback_data(applicationmap, 0, setup_dynamic_feature, features, &res);
00620 
00621    return res;
00622 }

static int setup_dynamic_feature ( void *  obj,
void *  arg,
void *  data,
int  flags 
) [static]

static void stimulate_attended_transfer ( struct attended_transfer_properties props,
enum attended_transfer_stimulus  stimulus 
) [static]

Definition at line 1528 of file bridge_basic.c.

References ao2_lock, ao2_unlock, ast_calloc, ast_cond_signal, AST_LIST_INSERT_TAIL, ast_log, attended_transfer_properties::cond, LOG_ERROR, stimulus_list::stimulus, and attended_transfer_properties::stimulus_queue.

Referenced by atxfer_abort(), atxfer_complete(), atxfer_swap(), atxfer_threeway(), atxfer_transferer_hangup(), recall_callback(), recall_pull(), transfer_pull(), and transfer_target_framehook_cb().

01530 {
01531    struct stimulus_list *list;
01532 
01533    list = ast_calloc(1, sizeof(*list));
01534    if (!list) {
01535       ast_log(LOG_ERROR, "Unable to push event to attended transfer queue. Expect transfer to fail\n");
01536       return;
01537    }
01538 
01539    list->stimulus = stimulus;
01540    ao2_lock(props);
01541    AST_LIST_INSERT_TAIL(&props->stimulus_queue, list, next);
01542    ast_cond_signal(&props->cond);
01543    ao2_unlock(props);
01544 }

static int threeway_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2132 of file bridge_basic.c.

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

02133 {
02134    struct ast_channel *transferee_channel;
02135    struct ast_channel *target_channel;
02136 
02137    get_transfer_parties(props->transferer, props->transferee_bridge, props->target_bridge,
02138          &transferee_channel, &target_channel);
02139    bridge_merge(props->transferee_bridge, props->target_bridge, NULL, 0);
02140    play_sound(props->transfer_target, props->xfersound);
02141    play_sound(props->transferer, props->xfersound);
02142    publish_transfer_threeway(props, transferee_channel, target_channel);
02143 
02144    ast_channel_cleanup(transferee_channel);
02145    ast_channel_cleanup(target_channel);
02146    return 0;
02147 }

static void transfer_pull ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel,
struct attended_transfer_properties props 
) [static]

Definition at line 2835 of file bridge_basic.c.

References ao2_cleanup, ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, AST_LIST_FIRST, BRIDGE_CHANNEL_STATE_WAIT, NULL, RAII_VAR, ast_bridge_channel::state, stimulate_attended_transfer(), STIMULUS_TRANSFER_TARGET_HANGUP, STIMULUS_TRANSFEREE_HANGUP, attended_transfer_properties::transferee_bridge, and attended_transfer_properties::transferer.

Referenced by bridge_personality_atxfer_pull().

02836 {
02837    if (self->num_channels > 1 || bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
02838       return;
02839    }
02840 
02841    if (self->num_channels == 1) {
02842       RAII_VAR(struct ast_bridge_channel *, transferer_bridge_channel, NULL, ao2_cleanup);
02843 
02844       ast_channel_lock(props->transferer);
02845       transferer_bridge_channel = ast_channel_get_bridge_channel(props->transferer);
02846       ast_channel_unlock(props->transferer);
02847 
02848       if (!transferer_bridge_channel) {
02849          return;
02850       }
02851 
02852       if (AST_LIST_FIRST(&self->channels) != transferer_bridge_channel) {
02853          return;
02854       }
02855    }
02856 
02857    /* Reaching this point means that either
02858     * 1) The bridge has no channels in it
02859     * 2) The bridge has one channel, and it's the transferer
02860     * In either case, it indicates that the non-transferer parties
02861     * are no longer in the bridge.
02862     */
02863    if (self == props->transferee_bridge) {
02864       stimulate_attended_transfer(props, STIMULUS_TRANSFEREE_HANGUP);
02865    } else {
02866       stimulate_attended_transfer(props, STIMULUS_TRANSFER_TARGET_HANGUP);
02867    }
02868 }

static struct ast_frame* transfer_target_framehook_cb ( struct ast_channel chan,
struct ast_frame frame,
enum ast_framehook_event  event,
void *  data 
) [static, read]

Frame hook for transfer target channel.

This is used to determine if the transfer target or recall target has answered the outgoing call.

When an answer is detected, a stimulus is sent to the attended transfer monitor thread to indicate that the transfer target or recall target has answered.

Parameters:
chan The channel the framehook is attached to.
frame The frame being read or written.
event What is being done with the frame.
data The attended transfer properties.

Definition at line 2755 of file bridge_basic.c.

References AST_CONTROL_ANSWER, ast_debug, AST_FRAME_CONTROL, ast_framehook_detach(), AST_FRAMEHOOK_EVENT_READ, ast_frame::frametype, ast_frame_subclass::integer, stimulate_attended_transfer(), STIMULUS_RECALL_TARGET_ANSWER, STIMULUS_TRANSFER_TARGET_ANSWER, ast_frame::subclass, attended_transfer_properties::superstate, SUPERSTATE_TRANSFER, and attended_transfer_properties::target_framehook_id.

Referenced by attach_framehook().

02757 {
02758    struct attended_transfer_properties *props = data;
02759 
02760    if (event == AST_FRAMEHOOK_EVENT_READ &&
02761          frame && frame->frametype == AST_FRAME_CONTROL &&
02762          frame->subclass.integer == AST_CONTROL_ANSWER) {
02763 
02764       ast_debug(1, "Detected an answer for recall attempt on attended transfer %p\n", props);
02765       if (props->superstate == SUPERSTATE_TRANSFER) {
02766          stimulate_attended_transfer(props, STIMULUS_TRANSFER_TARGET_ANSWER);
02767       } else {
02768          stimulate_attended_transfer(props, STIMULUS_RECALL_TARGET_ANSWER);
02769       }
02770       ast_framehook_detach(chan, props->target_framehook_id);
02771       props->target_framehook_id = -1;
02772    }
02773 
02774    return frame;
02775 }

static int transfer_target_framehook_consume ( void *  data,
enum ast_frame_type  type 
) [static]

Callback function which informs upstream if we are consuming a frame of a specific type.

Definition at line 2778 of file bridge_basic.c.

References AST_FRAME_CONTROL.

Referenced by attach_framehook().

02779 {
02780    return (type == AST_FRAME_CONTROL ? 1 : 0);
02781 }

static void transfer_target_framehook_destroy_cb ( void *  data  )  [static]

Definition at line 2783 of file bridge_basic.c.

References ao2_cleanup.

Referenced by attach_framehook().

02784 {
02785    struct attended_transfer_properties *props = data;
02786    ao2_cleanup(props);
02787 }

static void unhold ( struct ast_channel chan  )  [static]

Helper method to take a channel in a bridge off hold.

Definition at line 1732 of file bridge_basic.c.

References ao2_cleanup, ast_assert, ast_bridge_channel_write_unhold(), ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_unlock, NULL, and RAII_VAR.

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

01733 {
01734    RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
01735 
01736    ast_channel_lock(chan);
01737    bridge_channel = ast_channel_get_bridge_channel(chan);
01738    ast_channel_unlock(chan);
01739 
01740    ast_assert(bridge_channel != NULL);
01741 
01742    ast_bridge_channel_write_unhold(bridge_channel);
01743 }

static enum attended_transfer_stimulus wait_for_stimulus ( struct attended_transfer_properties props  )  [static]

Definition at line 2926 of file bridge_basic.c.

References ao2_object_get_lockaddr(), ast_cond_timedwait, ast_cond_wait, ast_free_ptr, AST_LIST_REMOVE_HEAD, ast_tvadd(), ast_tvnow(), attended_transfer_properties::atxferloopdelay, attended_transfer_properties::atxfernoanswertimeout, attended_transfer_properties::cond, attended_transfer_state_properties::flags, lock, NULL, RAII_VAR, SCOPED_MUTEX, attended_transfer_properties::start, attended_transfer_properties::state, attended_transfer_properties::stimulus_queue, STIMULUS_TIMEOUT, TRANSFER_STATE_FLAG_TIMED, TRANSFER_STATE_FLAG_TIMER_LOOP_DELAY, and TRANSFER_STATE_FLAG_TIMER_RESET.

Referenced by attended_transfer_monitor_thread().

02927 {
02928    RAII_VAR(struct stimulus_list *, list, NULL, ast_free_ptr);
02929    SCOPED_MUTEX(lock, ao2_object_get_lockaddr(props));
02930 
02931    while (!(list = AST_LIST_REMOVE_HEAD(&props->stimulus_queue, next))) {
02932       if (!(state_properties[props->state].flags & TRANSFER_STATE_FLAG_TIMED)) {
02933          ast_cond_wait(&props->cond, lock);
02934       } else {
02935          struct timeval relative_timeout = { 0, };
02936          struct timeval absolute_timeout;
02937          struct timespec timeout_arg;
02938 
02939          if (state_properties[props->state].flags & TRANSFER_STATE_FLAG_TIMER_RESET) {
02940             props->start = ast_tvnow();
02941          }
02942 
02943          if (state_properties[props->state].flags & TRANSFER_STATE_FLAG_TIMER_LOOP_DELAY) {
02944             relative_timeout.tv_sec = props->atxferloopdelay;
02945          } else {
02946             /* Implied TRANSFER_STATE_FLAG_TIMER_ATXFER_NO_ANSWER */
02947             relative_timeout.tv_sec = props->atxfernoanswertimeout;
02948          }
02949 
02950          absolute_timeout = ast_tvadd(props->start, relative_timeout);
02951          timeout_arg.tv_sec = absolute_timeout.tv_sec;
02952          timeout_arg.tv_nsec = absolute_timeout.tv_usec * 1000;
02953 
02954          if (ast_cond_timedwait(&props->cond, lock, &timeout_arg) == ETIMEDOUT) {
02955             return STIMULUS_TIMEOUT;
02956          }
02957       }
02958    }
02959    return list->stimulus;
02960 }

static int wait_to_recall_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2630 of file bridge_basic.c.

References bridge_hold(), and attended_transfer_properties::transferee_bridge.

02631 {
02632    bridge_hold(props->transferee_bridge);
02633    return 0;
02634 }

static enum attended_transfer_state wait_to_recall_exit ( struct attended_transfer_properties props,
enum attended_transfer_stimulus  stimulus 
) [static]

static int wait_to_retransfer_enter ( struct attended_transfer_properties props  )  [static]

Definition at line 2504 of file bridge_basic.c.

References bridge_hold(), and attended_transfer_properties::transferee_bridge.

02505 {
02506    bridge_hold(props->transferee_bridge);
02507    return 0;
02508 }

static enum attended_transfer_state wait_to_retransfer_exit ( struct attended_transfer_properties props,
enum attended_transfer_stimulus  stimulus 
) [static]


Variable Documentation

Bridge basic class virtual method table.

Definition at line 3412 of file bridge_basic.c.

Referenced by ast_bridge_basic_new(), and ast_bridging_init_basic().

Initial value:

 {
   .type = "bridge-dtmf-features",
   .destroy = ast_free_ptr,
}

Definition at line 84 of file bridge_basic.c.

Definition at line 3414 of file bridge_basic.c.

Referenced by ast_bridging_init_basic(), and init_details().

Definition at line 3413 of file bridge_basic.c.

Referenced by ast_bridging_init_basic(), and init_details().

Definition at line 1949 of file bridge_basic.c.

const char* stimulus_strs[]

String representations of the various stimuli.

Used for debugging purposes

Definition at line 1271 of file bridge_basic.c.


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