FreeSWITCH API Documentation  1.7.0
Data Structures | Macros | Typedefs | Functions | Variables
switch_ivr_bridge.c File Reference
#include <switch.h>
+ Include dependency graph for switch_ivr_bridge.c:

Go to the source code of this file.

Data Structures

struct  switch_ivr_bridge_data
 

Macros

#define DEFAULT_LEAD_FRAMES   10
 

Typedefs

typedef struct
switch_ivr_bridge_data 
switch_ivr_bridge_data_t
 

Functions

static void cleanup_proxy_mode_a (switch_core_session_t *session)
 
static void cleanup_proxy_mode_b (switch_core_session_t *session)
 
static void send_display (switch_core_session_t *session, switch_core_session_t *peer_session)
 
void switch_ivr_bridge_display (switch_core_session_t *session, switch_core_session_t *peer_session)
 
static void * audio_bridge_thread (switch_thread_t *thread, void *obj)
 
static void transfer_after_bridge (switch_core_session_t *session, const char *where)
 
static switch_status_t audio_bridge_on_exchange_media (switch_core_session_t *session)
 
static switch_status_t audio_bridge_on_routing (switch_core_session_t *session)
 
static switch_status_t audio_bridge_on_consume_media (switch_core_session_t *session)
 
static switch_status_t uuid_bridge_on_reset (switch_core_session_t *session)
 
static switch_status_t uuid_bridge_on_hibernate (switch_core_session_t *session)
 
static switch_status_t uuid_bridge_on_soft_execute (switch_core_session_t *session)
 
static switch_status_t sb_on_dtmf (switch_core_session_t *session, const switch_dtmf_t *dtmf, switch_dtmf_direction_t direction)
 
static switch_status_t hanguphook (switch_core_session_t *session)
 
static switch_status_t signal_bridge_on_hibernate (switch_core_session_t *session)
 
static switch_status_t signal_bridge_on_hangup (switch_core_session_t *session)
 
static void check_bridge_export (switch_channel_t *channel, switch_channel_t *peer_channel)
 
switch_status_t switch_ivr_signal_bridge (switch_core_session_t *session, switch_core_session_t *peer_session)
 Bridge Signalling from one session to another. More...
 
static void abort_call (switch_channel_t *caller_channel, switch_channel_t *peer_channel)
 
switch_status_t switch_ivr_multi_threaded_bridge (switch_core_session_t *session, switch_core_session_t *peer_session, switch_input_callback_function_t input_callback, void *session_data, void *peer_session_data)
 
switch_status_t switch_ivr_uuid_bridge (const char *originator_uuid, const char *originatee_uuid)
 Bridge two existing sessions. More...
 
switch_status_t switch_ivr_find_bridged_uuid (const char *uuid, char *b_uuid, switch_size_t blen)
 
void switch_ivr_intercept_session (switch_core_session_t *session, const char *uuid, switch_bool_t bleg)
 

Variables

static const
switch_state_handler_table_t 
audio_bridge_peer_state_handlers
 
static const
switch_state_handler_table_t 
uuid_bridge_state_handlers
 
static const
switch_state_handler_table_t 
signal_bridge_state_handlers
 

Macro Definition Documentation

#define DEFAULT_LEAD_FRAMES   10

Definition at line 33 of file switch_ivr_bridge.c.

Referenced by audio_bridge_thread().

Typedef Documentation

Definition at line 311 of file switch_ivr_bridge.c.

Function Documentation

static void abort_call ( switch_channel_t caller_channel,
switch_channel_t peer_channel 
)
static

Definition at line 1411 of file switch_ivr_bridge.c.

References SWITCH_CAUSE_ORIGINATOR_CANCEL, switch_channel_get_cause(), and switch_channel_hangup.

Referenced by switch_ivr_multi_threaded_bridge().

1412 {
1413  switch_call_cause_t cause = switch_channel_get_cause(caller_channel);
1414 
1415  if (!cause) {
1417  }
1418 
1419  switch_channel_hangup(peer_channel, cause);
1420 }
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
switch_call_cause_t
switch_call_cause_t switch_channel_get_cause(_In_ switch_channel_t *channel)
return the cause code for a given channel
static switch_status_t audio_bridge_on_consume_media ( switch_core_session_t session)
static

Definition at line 909 of file switch_ivr_bridge.c.

References switch_channel_get_name(), SWITCH_CHANNEL_SESSION_LOG, switch_core_session_get_channel(), SWITCH_LOG_DEBUG, switch_log_printf(), and SWITCH_STATUS_FALSE.

910 {
912 
914 
915  /* put the channel in a passive state so we can loop audio to it */
916  return SWITCH_STATUS_FALSE;
917 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
static switch_status_t audio_bridge_on_exchange_media ( switch_core_session_t session)
static

Definition at line 839 of file switch_ivr_bridge.c.

References audio_bridge_thread(), switch_ivr_bridge_data::b_uuid, CF_ANSWERED, CF_INNER_BRIDGE, CF_INTERCEPT, CF_INTERCEPTED, CF_REDIRECT, CF_TRANSFER, CF_XFER_ZOMBIE, switch_ivr_bridge_data::clean_exit, CS_EXCHANGE_MEDIA, CS_HANGUP, CS_PARK, CS_ROUTING, switch_ivr_bridge_data::session, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, SWITCH_CAUSE_NORMAL_CLEARING, SWITCH_CAUSE_ORIGINATOR_CANCEL, SWITCH_CAUSE_PICKED_OFF, switch_channel_clear_flag(), switch_channel_clear_state_handler(), switch_channel_get_private(), switch_channel_get_state(), switch_channel_get_variable, switch_channel_hangup, switch_channel_set_private(), switch_channel_set_state, switch_channel_set_variable, switch_channel_test_flag(), switch_core_session_get_channel(), switch_core_session_reset(), switch_ivr_park_session(), SWITCH_PARK_AFTER_BRIDGE_VARIABLE, SWITCH_STATUS_FALSE, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE, SWITCH_TRUE, switch_true(), and transfer_after_bridge().

840 {
842  switch_ivr_bridge_data_t *bd = switch_channel_get_private(channel, "_bridge_");
844  const char *var;
845 
846  if (bd) {
847  switch_channel_set_private(channel, "_bridge_", NULL);
848  if (bd->session == session && *bd->b_uuid) {
849  audio_bridge_thread(NULL, (void *) bd);
851  } else {
853  }
854  } else {
856  }
858 
859  state = switch_channel_get_state(channel);
860 
862  !switch_channel_test_flag(channel, CF_XFER_ZOMBIE) && bd && !bd->clean_exit && state != CS_PARK && state != CS_ROUTING &&
864 
866  switch_ivr_park_session(session);
867  return SWITCH_STATUS_FALSE;
868  } else if (state < CS_HANGUP && (var = switch_channel_get_variable(channel, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE))) {
869  transfer_after_bridge(session, var);
870  return SWITCH_STATUS_FALSE;
871  }
872 
876  return SWITCH_STATUS_FALSE;
877  } else {
878  if (switch_channel_test_flag(channel, CF_INTERCEPT)) {
880  } else {
881  if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
883  } else {
885  }
886  }
887  }
888  }
889 
891  switch_channel_set_variable(channel, "park_timeout", "3");
893  }
894 
895  return SWITCH_STATUS_FALSE;
896 }
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
switch_core_session_t * session
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
#define SWITCH_PARK_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:217
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
char b_uuid[SWITCH_UUID_FORMATTED_LENGTH+1]
void switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
clear a state handler table from a given channel
#define switch_channel_get_variable(_c, _v)
void switch_ivr_park_session(switch_core_session_t *session)
Definition: switch_ivr.c:3411
switch_channel_state_t
Channel States (these are the defaults, CS_SOFT_EXECUTE, CS_EXCHANGE_MEDIA, and CS_CONSUME_MEDIA are ...
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
static void transfer_after_bridge(switch_core_session_t *session, const char *where)
static const switch_state_handler_table_t audio_bridge_peer_state_handlers
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_channel_set_variable(_channel, _var, _val)
#define SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:219
static void * audio_bridge_thread(switch_thread_t *thread, void *obj)
static switch_status_t audio_bridge_on_routing ( switch_core_session_t session)
static

Definition at line 898 of file switch_ivr_bridge.c.

References CS_CONSUME_MEDIA, switch_channel_get_name(), SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_state, switch_core_session_get_channel(), SWITCH_LOG_DEBUG, switch_log_printf(), and SWITCH_STATUS_FALSE.

899 {
901 
902  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CUSTOM ROUTING\n", switch_channel_get_name(channel));
903 
904  /* put the channel in a passive state so we can loop audio to it */
906  return SWITCH_STATUS_FALSE;
907 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
static void* audio_bridge_thread ( switch_thread_t thread,
void *  obj 
)
static

Definition at line 313 of file switch_ivr_bridge.c.

References switch_codec_implementation::actual_samples_per_second, switch_ivr_bridge_data::b_uuid, switch_frame::buflen, CF_3P_NOMEDIA_REQUESTED, CF_ACCEPT_CNG, CF_ANSWERED, CF_BRIDGE_NOWRITE, CF_BRIDGE_ORIGINATOR, CF_BRIDGED, CF_BYPASS_MEDIA_AFTER_BRIDGE, CF_EARLY_MEDIA, CF_HANGUP_HELD, CF_HOLD, CF_HOLD_ON_BRIDGE, CF_INNER_BRIDGE, CF_INTERCEPT, CF_INTERCEPTED, CF_LEG_HOLDING, CF_NOT_READY, CF_REDIRECT, CF_RESET, CF_SUSPEND, CF_TRANSFER, CF_VIDEO, CF_VIDEO_BLANK, CF_VIDEO_BREAK, switch_ivr_bridge_data::clean_exit, switch_frame::codec, CS_EXECUTE, CS_PARK, CS_RESET, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, DEFAULT_LEAD_FRAMES, switch_ivr_bridge_data::done, switch_event::event_id, exec_app(), switch_core_session_message::from, switch_ivr_bridge_data::input_callback, switch_core_session_message::message_id, switch_codec_implementation::microseconds_per_packet, switch_codec_implementation::number_of_channels, switch_core_session_message::numeric_arg, switch_ivr_bridge_data::other_leg_data, switch_frame::samples, switch_ivr_bridge_data::session, switch_ivr_bridge_data::session_data, SFF_CNG, SMF_REBRIDGE, switch_ivr_bridge_data::stream_id, switch_core_session_message::string_arg, SWITCH_API_BRIDGE_END_VARIABLE, SWITCH_API_BRIDGE_START_VARIABLE, SWITCH_BRIDGE_VARIABLE, SWITCH_CALL_DIRECTION_INBOUND, SWITCH_CALL_DIRECTION_OUTBOUND, switch_caller_extension_add_application(), switch_caller_extension_new(), SWITCH_CAUSE_ALLOTTED_TIMEOUT, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, SWITCH_CAUSE_NONE, SWITCH_CAUSE_NORMAL_CLEARING, switch_channel_answer, switch_channel_api_on(), switch_channel_clear_flag(), switch_channel_dequeue_dtmf(), switch_channel_direction(), switch_channel_down_nosig, switch_channel_execute_on(), SWITCH_CHANNEL_EXECUTE_ON_POST_BRIDGE_VARIABLE, SWITCH_CHANNEL_EXECUTE_ON_PRE_BRIDGE_VARIABLE, switch_channel_get_cause(), switch_channel_get_name(), switch_channel_get_state(), switch_channel_get_variable, switch_channel_get_variable_dup(), switch_channel_hangup, switch_channel_has_dtmf(), switch_channel_mark_hold(), switch_channel_media_ack, switch_channel_media_up, switch_channel_pass_callee_id(), switch_channel_pre_answer, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_caller_extension(), switch_channel_set_flag, switch_channel_set_state, switch_channel_set_variable, switch_channel_stop_broadcast, switch_channel_test_flag(), switch_channel_up, switch_channel_up_nosig, switch_channel_wait_for_flag(), SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, switch_core_codec_destroy(), switch_core_codec_init, switch_core_media_check_video_function(), switch_core_media_end_video_function(), switch_core_session_dequeue_event(), switch_core_session_execute_application_async(), switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_impl(), switch_core_session_get_uuid(), switch_core_session_kill_channel, switch_core_session_locate, switch_core_session_private_event_count(), switch_core_session_read_frame(), switch_core_session_read_video_frame(), switch_core_session_receive_event(), switch_core_session_receive_message, switch_core_session_reset(), switch_core_session_rwunlock(), switch_core_session_send_dtmf(), switch_core_session_video_reset(), switch_core_session_write_frame(), switch_core_session_write_video_frame(), switch_epoch_time_now(), SWITCH_EVENT_COMMAND, switch_event_destroy(), SWITCH_EVENT_MESSAGE, SWITCH_EXEC_AFTER_BRIDGE_APP_VARIABLE, SWITCH_EXEC_AFTER_BRIDGE_ARG_VARIABLE, SWITCH_FALSE, switch_generate_sln_silence(), SWITCH_INPUT_TYPE_DTMF, SWITCH_INPUT_TYPE_EVENT, SWITCH_IO_FLAG_NONE, switch_ivr_3p_nomedia(), switch_ivr_bridge_display(), switch_ivr_parse_all_messages(), switch_ivr_parse_next_event(), SWITCH_LOG_CRIT, SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_MESSAGE_INDICATE_BRIDGE, SWITCH_MESSAGE_INDICATE_HOLD, SWITCH_MESSAGE_INDICATE_UNBRIDGE, SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, SWITCH_SIG_BREAK, SWITCH_STATUS_BREAK, SWITCH_STATUS_IGNORE, SWITCH_STATUS_SUCCESS, switch_stristr(), switch_test_flag, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE, SWITCH_TRUE, switch_true(), switch_yield, and zstr.

Referenced by audio_bridge_on_exchange_media(), and switch_ivr_multi_threaded_bridge().

314 {
315  switch_ivr_bridge_data_t *data = obj;
316  int stream_id = 0, pre_b = 0, ans_a = 0, ans_b = 0, originator = 0;
317  switch_input_callback_function_t input_callback;
318  switch_core_session_message_t msg = { 0 };
319  void *user_data;
320  switch_channel_t *chan_a, *chan_b;
321  switch_frame_t *read_frame;
322  switch_core_session_t *session_a, *session_b;
323  uint32_t read_frame_count = 0;
324  const char *app_name = NULL, *app_arg = NULL;
325  int inner_bridge = 0, exec_check = 0;
326  switch_codec_t silence_codec = { 0 };
327  switch_frame_t silence_frame = { 0 };
328  int16_t silence_data[SWITCH_RECOMMENDED_BUFFER_SIZE / 2] = { 0 };
329  const char *silence_var;
330  int silence_val = 0, bypass_media_after_bridge = 0;
331  const char *bridge_answer_timeout = NULL;
332  int bridge_filter_dtmf, answer_timeout, sent_update = 0;
333  time_t answer_limit = 0;
334  const char *exec_app = NULL;
335  const char *exec_data = NULL;
336  switch_codec_implementation_t read_impl = { 0 };
337 
338 #ifdef SWITCH_VIDEO_IN_THREADS
339  struct vid_helper vh = { 0 };
340  uint32_t vid_launch = 0;
341 #endif
342  data->clean_exit = 0;
343 
344  session_a = data->session;
345  if (!(session_b = switch_core_session_locate(data->b_uuid))) {
346  return NULL;
347  }
348 
349  switch_core_session_get_read_impl(session_a, &read_impl);
350 
351 
352  input_callback = data->input_callback;
353  user_data = data->session_data;
354  stream_id = data->stream_id;
355 
356  chan_a = switch_core_session_get_channel(session_a);
357  chan_b = switch_core_session_get_channel(session_b);
358 
359  if ((exec_app = switch_channel_get_variable(chan_a, "bridge_pre_execute_app"))) {
360  exec_data = switch_channel_get_variable(chan_a, "bridge_pre_execute_data");
361  }
362 
363  bypass_media_after_bridge = switch_channel_test_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE);
365 
366  ans_a = switch_channel_test_flag(chan_a, CF_ANSWERED);
367 
368  if ((originator = switch_channel_test_flag(chan_a, CF_BRIDGE_ORIGINATOR))) {
369  pre_b = switch_channel_test_flag(chan_a, CF_EARLY_MEDIA);
370  ans_b = switch_channel_test_flag(chan_b, CF_ANSWERED);
371  }
372 
373  inner_bridge = switch_channel_test_flag(chan_a, CF_INNER_BRIDGE);
374 
375  if (!switch_channel_test_flag(chan_a, CF_ANSWERED) && (bridge_answer_timeout = switch_channel_get_variable(chan_a, "bridge_answer_timeout"))) {
376  if ((answer_timeout = atoi(bridge_answer_timeout)) < 0) {
377  answer_timeout = 0;
378  } else {
379  answer_limit = switch_epoch_time_now(NULL) + answer_timeout;
380  }
381  }
382 
385 
387 
388  switch_channel_wait_for_flag(chan_b, CF_BRIDGED, SWITCH_TRUE, 10000, chan_a);
389 
390  if (!switch_channel_test_flag(chan_b, CF_BRIDGED)) {
392  || switch_channel_get_state(chan_b) == CS_RESET)) {
394  }
395  goto end_of_bridge_loop;
396  }
397 
398  if (bypass_media_after_bridge) {
399  const char *source_a = switch_channel_get_variable(chan_a, "source");
400  const char *source_b = switch_channel_get_variable(chan_b, "source");
401 
402  if (!source_a) source_a = "";
403  if (!source_b) source_b = "";
404 
405  if (switch_stristr("loopback", source_a) || switch_stristr("loopback", source_b)) {
406  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_WARNING, "Cannot bypass media while bridged to a loopback address.\n");
407  bypass_media_after_bridge = 0;
408  }
409  }
410 
411  if ((silence_var = switch_channel_get_variable(chan_a, "bridge_generate_comfort_noise"))) {
412 
413  if (!switch_channel_media_up(chan_a)) {
414  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_ERROR, "Channel has no media!\n");
415  goto end_of_bridge_loop;
416  }
417 
418  if (switch_true(silence_var)) {
419  silence_val = 1400;
420  } else {
421  if ((silence_val = atoi(silence_var)) < -1) {
422  silence_val = 0;
423  }
424  }
425 
426  if (silence_val) {
427  if (switch_core_codec_init(&silence_codec,
428  "L16",
429  NULL,
430  NULL,
431  read_impl.actual_samples_per_second,
432  read_impl.microseconds_per_packet / 1000,
433  1,
436 
437  silence_val = 0;
438  } else {
439  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "Setup generated silence from %s to %s at %d\n", switch_channel_get_name(chan_a),
440  switch_channel_get_name(chan_b), silence_val);
441  silence_frame.codec = &silence_codec;
442  silence_frame.data = silence_data;
443  silence_frame.buflen = sizeof(silence_data);
444  silence_frame.datalen = read_impl.decoded_bytes_per_packet;
445  silence_frame.samples = silence_frame.datalen / sizeof(int16_t);
446  }
447  }
448  }
449 
450  bridge_filter_dtmf = switch_true(switch_channel_get_variable(chan_a, "bridge_filter_dtmf"));
451 
452  for (;;) {
453  switch_channel_state_t b_state;
454  switch_status_t status;
455  switch_event_t *event;
456 
457  if (switch_channel_test_flag(chan_a, CF_TRANSFER)) {
458  data->clean_exit = 1;
459  }
460 
461  if (data->clean_exit || switch_channel_test_flag(chan_b, CF_TRANSFER)) {
464  goto end_of_bridge_loop;
465  }
466 
467  if (!switch_channel_test_flag(chan_b, CF_BRIDGED)) {
468  goto end_of_bridge_loop;
469  }
470 
471  if (!switch_channel_ready(chan_a)) {
472  if (switch_channel_up(chan_a)) {
473  data->clean_exit = 1;
474  }
475  goto end_of_bridge_loop;
476  }
477 
478  if ((b_state = switch_channel_down_nosig(chan_b))) {
479  goto end_of_bridge_loop;
480  }
481 
483  switch_core_session_message_t hmsg = { 0 };
486  hmsg.from = __FILE__;
487  hmsg.numeric_arg = 1;
488  switch_core_session_receive_message(session_a, &hmsg);
489  }
490 
491  if (read_frame_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a) && switch_core_session_private_event_count(session_a)) {
493  msg.numeric_arg = 42;
494  msg.string_arg = data->b_uuid;
496  msg.from = __FILE__;
497  switch_core_session_receive_message(session_a, &msg);
498  switch_ivr_parse_next_event(session_a);
500  switch_core_session_receive_message(session_a, &msg);
503  }
504 
506 
507  if (!inner_bridge && (switch_channel_test_flag(chan_a, CF_SUSPEND) || switch_channel_test_flag(chan_b, CF_SUSPEND))) {
508  status = switch_core_session_read_frame(session_a, &read_frame, SWITCH_IO_FLAG_NONE, stream_id);
509 
510  if (!SWITCH_READ_ACCEPTABLE(status)) {
511  goto end_of_bridge_loop;
512  }
513  continue;
514  }
515 #ifdef SWITCH_VIDEO_IN_THREADS
516  if (switch_channel_test_flag(chan_a, CF_VIDEO) && switch_channel_test_flag(chan_b, CF_VIDEO) && !vid_launch) {
517  vid_launch++;
518  vh.session_a = session_a;
519  vh.session_b = session_b;
522  launch_video(&vh);
523  } else {
524  if (switch_channel_test_flag(chan_a, CF_VIDEO)) {
526  }
527 
528  if (switch_channel_test_flag(chan_b, CF_VIDEO)) {
530  }
531  }
532 #endif
533 
534  if (read_frame_count >= DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a)) {
535 
536  if (!exec_check) {
538 
539  if (!inner_bridge) {
541  }
542  exec_check = 1;
543  }
544 
545  if (exec_app) {
546  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s Bridge execute app %s(%s)\n",
547  switch_channel_get_name(chan_a), exec_app, exec_data);
548 
549  switch_core_session_execute_application_async(session_a, exec_app, exec_data);
550  exec_app = exec_data = NULL;
551  }
552 
553  if ((bypass_media_after_bridge || switch_channel_test_flag(chan_b, CF_BYPASS_MEDIA_AFTER_BRIDGE)) && switch_channel_test_flag(chan_a, CF_ANSWERED)
556  bypass_media_after_bridge = 0;
558  goto end_of_bridge_loop;
559  }
560  }
561 
562  /* if 1 channel has DTMF pass it to the other */
563  while (switch_channel_has_dtmf(chan_a)) {
564  switch_dtmf_t dtmf = { 0, 0 };
565  if (switch_channel_dequeue_dtmf(chan_a, &dtmf) == SWITCH_STATUS_SUCCESS) {
566  int send_dtmf = 1;
567 
568  if (input_callback) {
569  switch_status_t cb_status = input_callback(session_a, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0);
570 
571  if (cb_status == SWITCH_STATUS_IGNORE) {
572  send_dtmf = 0;
573  } else if (cb_status != SWITCH_STATUS_SUCCESS) {
574  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s ended call via DTMF\n", switch_channel_get_name(chan_a));
576  goto end_of_bridge_loop;
577  }
578  }
579 
580  if (bridge_filter_dtmf) {
581  send_dtmf = 0;
582  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "Dropping filtered DTMF received on %s\n", switch_channel_get_name(chan_a));
583  }
584 
585  if (send_dtmf) {
586  switch_core_session_send_dtmf(session_b, &dtmf);
588  }
589  }
590  }
591 
593  if (input_callback) {
594  status = input_callback(session_a, event, SWITCH_INPUT_TYPE_EVENT, user_data, 0);
595  }
596 
597  if ((event->event_id != SWITCH_EVENT_COMMAND && event->event_id != SWITCH_EVENT_MESSAGE)
598  || switch_core_session_receive_event(session_b, &event) != SWITCH_STATUS_SUCCESS) {
599  switch_event_destroy(&event);
600  }
601 
602  }
603 
604  if (!switch_channel_test_flag(chan_a, CF_ANSWERED) && answer_limit && switch_epoch_time_now(NULL) > answer_limit) {
605  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "Answer timeout hit on %s.\n", switch_channel_get_name(chan_a));
606  if (switch_true(switch_channel_get_variable_dup(chan_a, "continue_on_answer_timeout", SWITCH_FALSE, -1))) {
607  data->clean_exit = 1;
608  goto end_of_bridge_loop;
609  } else {
611  }
612  }
613 
614  if (!switch_channel_test_flag(chan_a, CF_ANSWERED)) {
615  if (originator) {
616  if (!ans_b && switch_channel_test_flag(chan_b, CF_ANSWERED)) {
617  switch_channel_pass_callee_id(chan_b, chan_a);
619  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s Media Establishment Failed.\n", switch_channel_get_name(chan_a));
620  goto end_of_bridge_loop;
621  }
622  ans_a = 1;
623  } else if (!pre_b && switch_channel_test_flag(chan_b, CF_EARLY_MEDIA)) {
625  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s Media Establishment Failed.\n", switch_channel_get_name(chan_a));
626  goto end_of_bridge_loop;
627  }
628  pre_b = 1;
629  }
630  if (!pre_b) {
631  switch_yield(10000);
632  continue;
633  }
634  } else {
635  ans_a = switch_channel_test_flag(chan_b, CF_ANSWERED);
636  }
637  }
638 
639  if (ans_a != ans_b) {
640  switch_channel_t *un = ans_a ? chan_b : chan_a;
641  switch_channel_t *a = un == chan_b ? chan_a : chan_b;
642 
644  if (switch_channel_direction(a) == SWITCH_CALL_DIRECTION_OUTBOUND || (un == chan_a && !originator)) {
646  }
647 
649  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s Media Establishment Failed.\n", switch_channel_get_name(un));
650  goto end_of_bridge_loop;
651  }
652 
653  if (ans_a) {
654  ans_b = 1;
655  } else {
656  ans_a = 1;
657  }
658  }
659  }
660 
661  if (originator && !ans_b) ans_b = switch_channel_test_flag(chan_b, CF_ANSWERED);
662 
663  if (originator && !sent_update && ans_a && ans_b && switch_channel_media_ack(chan_a) && switch_channel_media_ack(chan_b)) {
664  switch_ivr_bridge_display(session_a, session_b);
665  sent_update = 1;
666  }
667 #ifndef SWITCH_VIDEO_IN_THREADS
669  /* read video from 1 channel and write it to the other */
670  status = switch_core_session_read_video_frame(session_a, &read_frame, SWITCH_IO_FLAG_NONE, 0);
671 
672  if (!SWITCH_READ_ACCEPTABLE(status)) {
673  goto end_of_bridge_loop;
674  }
675 
677  }
678 #endif
679 
680  /* read audio from 1 channel and write it to the other */
681  status = switch_core_session_read_frame(session_a, &read_frame, SWITCH_IO_FLAG_NONE, stream_id);
682 
683  if (SWITCH_READ_ACCEPTABLE(status)) {
684  read_frame_count++;
685  if (switch_test_flag(read_frame, SFF_CNG)) {
686  if (silence_val) {
687  switch_generate_sln_silence((int16_t *) silence_frame.data, silence_frame.samples,
688  read_impl.number_of_channels, silence_val);
689  read_frame = &silence_frame;
690  } else if (!switch_channel_test_flag(chan_b, CF_ACCEPT_CNG)) {
691  continue;
692  }
693  }
694 
696  continue;
697  }
698 
700  if (switch_core_session_write_frame(session_b, read_frame, SWITCH_IO_FLAG_NONE, stream_id) != SWITCH_STATUS_SUCCESS) {
702  "%s ending bridge by request from write function\n", switch_channel_get_name(chan_b));
703  goto end_of_bridge_loop;
704  }
705  }
706  } else {
707  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s ending bridge by request from read function\n", switch_channel_get_name(chan_a));
708  goto end_of_bridge_loop;
709  }
710  }
711 
712  end_of_bridge_loop:
713 
714 #ifdef SWITCH_VIDEO_IN_THREADS
715  if (vh.up > 0) {
716  vh.up = -1;
718  //switch_channel_set_flag(chan_b, CF_NOT_READY);
721  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "Ending video thread.\n");
722  }
723 #endif
724 
725 
726  if (silence_val) {
727  switch_core_codec_destroy(&silence_codec);
728  }
729 
731 
732  if (!inner_bridge) {
734  }
735 
736  if (!inner_bridge && switch_channel_up_nosig(chan_a)) {
738  switch_caller_extension_t *extension = NULL;
739  if ((extension = switch_caller_extension_new(session_a, app_name, app_name)) == 0) {
740  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_CRIT, "memory error!\n");
741  goto end;
742  }
744 
745  switch_caller_extension_add_application(session_a, extension, (char *) app_name, app_arg);
746  switch_channel_set_caller_extension(chan_a, extension);
747 
748  if (switch_channel_get_state(chan_a) == CS_EXECUTE) {
750  } else {
752  }
753  }
754  }
755 
756  end:
757 
758 #ifdef SWITCH_VIDEO_IN_THREADS
760  if (vh.up == 1) {
761  vh.up = -1;
762  }
763 
768 
769  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "Ending video thread.\n");
773  }
774 #endif
775 
776 
777 
780  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "BRIDGE THREAD DONE [%s]\n", switch_channel_get_name(chan_a));
782 
784  if (switch_channel_ready(chan_b) &&
786  const char *ext = switch_channel_get_variable(chan_a, "hold_hangup_xfer_exten");
787 
789 
790  if (zstr(ext)) {
792  if (cause == SWITCH_CAUSE_NONE) {
794  }
795  switch_channel_hangup(chan_b, cause);
796  } else {
798  }
799  }
800 
803  }
804  }
805 
808  }
809 
812 
814  data->done = 1;
817 
818  switch_core_session_rwunlock(session_b);
819  return NULL;
820 }
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
#define switch_channel_answer(channel)
Answer a channel (initiate/acknowledge a successful connection)
switch_status_t switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix)
switch_event_types_t event_id
Definition: switch_event.h:82
#define SWITCH_CHANNEL_SESSION_LOG(x)
An Abstract Representation of a dialplan extension.
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
switch_core_session_t * session
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
#define SWITCH_API_BRIDGE_END_VARIABLE
Definition: switch_types.h:172
#define switch_channel_stop_broadcast(_channel)
#define switch_channel_up(_channel)
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:557
switch_status_t switch_core_session_read_video_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a video frame from a session.
Representation of an event.
Definition: switch_event.h:80
struct switch_ivr_bridge_data * other_leg_data
#define switch_channel_ready(_channel)
void switch_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t channels, uint32_t divisor)
Generate static noise.
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
const char * switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup, int idx)
Retrieve a variable from a given channel.
switch_status_t switch_core_session_execute_application_async(switch_core_session_t *session, const char *app, const char *arg)
#define SWITCH_CHANNEL_EXECUTE_ON_PRE_BRIDGE_VARIABLE
Definition: switch_types.h:157
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
switch_codec_t * codec
Definition: switch_frame.h:45
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
void switch_core_media_end_video_function(switch_core_session_t *session)
#define zstr(x)
Definition: switch_utils.h:281
switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a frame to a session.
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_ivr_parse_next_event(switch_core_session_t *session)
Definition: switch_ivr.c:755
#define SWITCH_EXEC_AFTER_BRIDGE_APP_VARIABLE
Definition: switch_types.h:221
#define SWITCH_CHANNEL_EXECUTE_ON_POST_BRIDGE_VARIABLE
Definition: switch_types.h:158
void switch_channel_mark_hold(switch_channel_t *channel, switch_bool_t on)
uint32_t buflen
Definition: switch_frame.h:59
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
int switch_core_media_check_video_function(switch_core_session_t *session)
uint32_t datalen
Definition: switch_frame.h:57
static void exec_app(switch_core_session_t *session, char *app_str)
char b_uuid[SWITCH_UUID_FORMATTED_LENGTH+1]
switch_status_t(* switch_input_callback_function_t)(switch_core_session_t *session, void *input, switch_input_type_t input_type, void *buf, unsigned int buflen)
switch_status_t switch_core_session_send_dtmf(_In_ switch_core_session_t *session, const switch_dtmf_t *dtmf)
Send DTMF to a session.
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_channel_dequeue_dtmf(_In_ switch_channel_t *channel, _In_ switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given channel.
#define DEFAULT_LEAD_FRAMES
#define switch_channel_down_nosig(_channel)
#define SWITCH_API_BRIDGE_START_VARIABLE
Definition: switch_types.h:173
void switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension)
Assign a caller extension to a given channel.
An abstraction of a data frame.
Definition: switch_frame.h:43
void switch_caller_extension_add_application(_In_ switch_core_session_t *session, _In_ switch_caller_extension_t *caller_extension, _In_z_ const char *application_name, _In_z_ const char *extra_data)
Add an application (instruction) to the given extension.
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
#define SWITCH_BRIDGE_VARIABLE
Definition: switch_types.h:199
switch_call_cause_t
switch_caller_extension_t * switch_caller_extension_new(_In_ switch_core_session_t *session, _In_z_ const char *extension_name, _In_z_ const char *extension_number)
Create a new extension with desired parameters.
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
void switch_core_session_video_reset(switch_core_session_t *session)
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
switch_input_callback_function_t input_callback
switch_status_t switch_core_session_write_video_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Write a video frame to a session.
switch_channel_state_t
Channel States (these are the defaults, CS_SOFT_EXECUTE, CS_EXCHANGE_MEDIA, and CS_CONSUME_MEDIA are ...
switch_status_t switch_ivr_3p_nomedia(const char *uuid, switch_media_flag_t flags)
Definition: switch_ivr.c:1774
switch_status_t
Common return values.
#define SWITCH_EXEC_AFTER_BRIDGE_ARG_VARIABLE
Definition: switch_types.h:222
switch_status_t switch_core_session_dequeue_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event, switch_bool_t force)
DE-Queue an event on a given session.
switch_status_t switch_core_session_receive_event(_In_ switch_core_session_t *session, _Inout_ switch_event_t **event)
Send an event to a session translating it to it's native message format.
switch_size_t switch_channel_has_dtmf(_In_ switch_channel_t *channel)
Test for presence of DTMF on a given channel.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
uint32_t samples
Definition: switch_frame.h:61
uint32_t switch_core_session_private_event_count(_In_ switch_core_session_t *session)
Indicate the number of waiting private events on a session.
#define switch_channel_set_flag(_c, _f)
void switch_ivr_bridge_display(switch_core_session_t *session, switch_core_session_t *peer_session)
switch_call_direction_t switch_channel_direction(switch_channel_t *channel)
#define switch_channel_media_ack(_channel)
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:321
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
const char * switch_stristr(const char *instr, const char *str)
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_channel_up_nosig(_channel)
void switch_event_destroy(switch_event_t **event)
Destroy an event.
switch_status_t switch_channel_wait_for_flag(switch_channel_t *channel, switch_channel_flag_t want_flag, switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_channel_set_variable(_channel, _var, _val)
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
#define switch_core_session_kill_channel(session, sig)
Send a signal to a channel.
Definition: switch_core.h:1352
switch_status_t switch_channel_api_on(switch_channel_t *channel, const char *variable_prefix)
#define SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:219
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
switch_status_t switch_channel_pass_callee_id(switch_channel_t *channel, switch_channel_t *other_channel)
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
#define switch_channel_media_up(_channel)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_call_cause_t switch_channel_get_cause(_In_ switch_channel_t *channel)
return the cause code for a given channel
switch_status_t switch_ivr_parse_all_messages(switch_core_session_t *session)
Definition: switch_ivr.c:801
static void check_bridge_export ( switch_channel_t channel,
switch_channel_t peer_channel 
)
static

Definition at line 1326 of file switch_ivr_bridge.c.

References switch_caller_profile::callee_id_name, switch_caller_profile::callee_id_number, switch_caller_profile::pool, SWITCH_BRIDGE_EXPORT_VARS_VARIABLE, switch_channel_get_caller_profile(), switch_channel_process_export(), and switch_core_strdup.

Referenced by switch_ivr_multi_threaded_bridge(), and switch_ivr_signal_bridge().

1327 {
1328  switch_caller_profile_t *originator_cp, *originatee_cp;
1329 
1330  originator_cp = switch_channel_get_caller_profile(channel);
1331  originatee_cp = switch_channel_get_caller_profile(peer_channel);
1332 
1333  originator_cp->callee_id_name = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_name);
1334  originator_cp->callee_id_number = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_number);
1335 
1336 
1339 }
Call Specific Data.
Definition: switch_caller.h:73
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
#define SWITCH_BRIDGE_EXPORT_VARS_VARIABLE
Definition: switch_types.h:195
const char * callee_id_number
Definition: switch_caller.h:89
void switch_channel_process_export(switch_channel_t *channel, switch_channel_t *peer_channel, switch_event_t *var_event, const char *export_varname)
switch_caller_profile_t * switch_channel_get_caller_profile(switch_channel_t *channel)
Retrieve the given channel's caller profile.
const char * callee_id_name
Definition: switch_caller.h:87
switch_memory_pool_t * pool
static void cleanup_proxy_mode_a ( switch_core_session_t session)
static

Definition at line 1776 of file switch_ivr_bridge.c.

References CF_3P_MEDIA_REQUESTED, CF_3P_NOMEDIA_REQUESTED, CF_PROXY_MODE, SWITCH_BRIDGE_UUID_VARIABLE, SWITCH_BRIDGE_VARIABLE, SWITCH_CAUSE_ATTENDED_TRANSFER, switch_channel_hangup, switch_channel_set_variable, switch_channel_test_flag(), switch_core_session_get_channel(), switch_core_session_get_partner, switch_core_session_rwunlock(), SWITCH_SIGNAL_BRIDGE_VARIABLE, and SWITCH_STATUS_SUCCESS.

Referenced by switch_ivr_uuid_bridge().

1777 {
1778  switch_core_session_t *sbsession;
1780  int done = 0;
1781 
1784  if (switch_core_session_get_partner(session, &sbsession) == SWITCH_STATUS_SUCCESS) {
1785  switch_channel_t *sbchannel = switch_core_session_get_channel(sbsession);
1786 
1787  if (switch_channel_test_flag(sbchannel, CF_PROXY_MODE)) {
1788  /* Clear this now, otherwise will cause the one we're interested in to hang up too...*/
1791  } else {
1792  done = 1;
1793  }
1794  switch_core_session_rwunlock(sbsession);
1795  }
1796  }
1797 
1798  if (done) return;
1799 
1803 
1804 }
#define SWITCH_SIGNAL_BRIDGE_VARIABLE
Definition: switch_types.h:201
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define SWITCH_BRIDGE_UUID_VARIABLE
Definition: switch_types.h:182
#define switch_core_session_get_partner(_session, _partner)
Definition: switch_core.h:1002
#define SWITCH_BRIDGE_VARIABLE
Definition: switch_types.h:199
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
#define switch_channel_set_variable(_channel, _var, _val)
static void cleanup_proxy_mode_b ( switch_core_session_t session)
static

Definition at line 1765 of file switch_ivr_bridge.c.

References CF_3P_MEDIA_REQUESTED, CF_MEDIA_TRANS, CF_PROXY_MODE, SMF_NONE, switch_channel_test_flag(), switch_core_session_get_channel(), switch_core_session_get_uuid(), and switch_ivr_media().

Referenced by uuid_bridge_on_reset().

1766 {
1768 
1769  if (switch_channel_test_flag(channel, CF_PROXY_MODE) &&
1772  }
1773 }
switch_status_t switch_ivr_media(const char *uuid, switch_media_flag_t flags)
Signal a session to request direct media access to it's remote end.
Definition: switch_ivr.c:1674
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
static switch_status_t hanguphook ( switch_core_session_t session)
static

Definition at line 1125 of file switch_ivr_bridge.c.

References CF_BRIDGE_ORIGINATOR, switch_core_session_message::from, switch_core_session_message::message_id, MESSAGE_STAMP_FFL, switch_core_session_message::string_arg, switch_channel_clear_flag_recursive(), switch_channel_event_set_data(), switch_channel_get_variable, switch_channel_test_flag(), switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_queue_message(), SWITCH_EVENT_CHANNEL_UNBRIDGE, switch_event_create, switch_event_fire, SWITCH_MESSAGE_INDICATE_UNBRIDGE, SWITCH_SIGNAL_BRIDGE_VARIABLE, and SWITCH_STATUS_SUCCESS.

Referenced by signal_bridge_on_hibernate().

1126 {
1127  switch_core_session_message_t *msg = NULL;
1128  switch_channel_t *channel = NULL;
1129  switch_event_t *event;
1130 
1131  channel = switch_core_session_get_channel(session);
1132 
1136  switch_channel_event_set_data(channel, event);
1137  switch_event_fire(&event);
1138  }
1139  }
1140 
1141 
1142  msg = switch_core_session_alloc(session, sizeof(*msg));
1143  MESSAGE_STAMP_FFL(msg);
1145  msg->from = __FILE__;
1147  switch_core_session_queue_message(session, msg);
1148 
1149  switch_core_event_hook_remove_state_change(session, hanguphook);
1150 
1151  return SWITCH_STATUS_SUCCESS;
1152 
1153 }
#define SWITCH_SIGNAL_BRIDGE_VARIABLE
Definition: switch_types.h:201
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
Representation of an event.
Definition: switch_event.h:80
switch_status_t switch_core_session_queue_message(_In_ switch_core_session_t *session, _In_ switch_core_session_message_t *message)
Queue a message on a session.
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_channel_get_variable(_c, _v)
static switch_status_t hanguphook(switch_core_session_t *session)
#define MESSAGE_STAMP_FFL(_m)
Definition: switch_core.h:173
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
void switch_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
static switch_status_t sb_on_dtmf ( switch_core_session_t session,
const switch_dtmf_t dtmf,
switch_dtmf_direction_t  direction 
)
static

Definition at line 1095 of file switch_ivr_bridge.c.

References CF_BRIDGE_ORIGINATOR, CS_EXECUTE, switch_dtmf_t::digit, switch_assert, switch_channel_get_private(), switch_channel_get_variable, switch_channel_set_state, switch_channel_test_flag(), switch_core_session_get_channel(), switch_core_session_locate, switch_core_session_rwunlock(), SWITCH_SIGNAL_BRIDGE_VARIABLE, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.

Referenced by signal_bridge_on_hangup(), and signal_bridge_on_hibernate().

1096 {
1097  switch_channel_t *channel = NULL;
1098  char *key;
1099 
1100  channel = switch_core_session_get_channel(session);
1101  switch_assert(channel != NULL);
1102 
1103  if ((key = (char *) switch_channel_get_private(channel, "__bridge_term_key")) && dtmf->digit == *key) {
1104  const char *uuid;
1105  switch_core_session_t *other_session;
1106 
1109  } else {
1110  if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
1111  switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
1112  switch_channel_set_state(other_channel, CS_EXECUTE);
1113  switch_core_session_rwunlock(other_session);
1114  } else {
1115  return SWITCH_STATUS_SUCCESS;
1116  }
1117  }
1118 
1119  return SWITCH_STATUS_FALSE;
1120  }
1121 
1122  return SWITCH_STATUS_SUCCESS;
1123 }
#define SWITCH_SIGNAL_BRIDGE_VARIABLE
Definition: switch_types.h:201
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_channel_get_variable(_c, _v)
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
#define switch_assert(expr)
static void send_display ( switch_core_session_t session,
switch_core_session_t peer_session 
)
static

Definition at line 231 of file switch_ivr_bridge.c.

References switch_caller_profile::callee_id_name, switch_caller_profile::callee_id_number, switch_caller_profile::caller_id_name, switch_caller_profile::caller_id_number, CF_BRIDGE_ORIGINATOR, switch_caller_profile::destination_number, switch_core_session_message::from, switch_core_session_message::message_id, MESSAGE_STAMP_FFL, switch_core_session_message::string_array_arg, switch_channel_get_caller_profile(), switch_channel_test_flag(), switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_queue_message(), switch_core_session_strdup, SWITCH_MESSAGE_INDICATE_DISPLAY, and zstr.

Referenced by switch_ivr_bridge_display().

232 {
233 
235  switch_caller_profile_t *caller_profile, *peer_caller_profile;
236  switch_channel_t *caller_channel, *peer_channel;
237  const char *name, *number, *p;
238 
239  caller_channel = switch_core_session_get_channel(session);
240  peer_channel = switch_core_session_get_channel(peer_session);
241 
242  caller_profile = switch_channel_get_caller_profile(caller_channel);
243  peer_caller_profile = switch_channel_get_caller_profile(peer_channel);
244 
245  if (switch_channel_test_flag(caller_channel, CF_BRIDGE_ORIGINATOR)) {
246  if (!zstr(peer_caller_profile->caller_id_name)) {
247  name = peer_caller_profile->caller_id_name;
248  } else {
249  name = caller_profile->caller_id_name;
250  }
251 
252  if (!zstr(peer_caller_profile->caller_id_number)) {
253  number = peer_caller_profile->caller_id_number;
254  } else {
255  number = caller_profile->caller_id_number;
256  }
257 
258  if (zstr(number)) {
259  number = "UNKNOWN";
260  }
261  } else {
262  name = caller_profile->callee_id_name;
263  number = caller_profile->callee_id_number;
264 
265  if (zstr(number)) {
266  number = caller_profile->destination_number;
267  }
268  }
269 
270 
271  if (zstr(name)) {
272  name = number;
273  }
274 
275  if ((p = strrchr(number, '/'))) {
276  number = p + 1;
277  }
278  if ((p = strrchr(name, '/'))) {
279  name = p + 1;
280  }
281 
282  msg = switch_core_session_alloc(peer_session, sizeof(*msg));
283  MESSAGE_STAMP_FFL(msg);
285  msg->string_array_arg[0] = switch_core_session_strdup(peer_session, name);
286  msg->string_array_arg[1] = switch_core_session_strdup(peer_session, number);
287  msg->from = __FILE__;
288  switch_core_session_queue_message(peer_session, msg);
289 
290 }
Call Specific Data.
Definition: switch_caller.h:73
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
const char * string_array_arg[MESSAGE_STRING_ARG_MAX]
Definition: switch_core.h:209
switch_status_t switch_core_session_queue_message(_In_ switch_core_session_t *session, _In_ switch_core_session_message_t *message)
Queue a message on a session.
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
#define zstr(x)
Definition: switch_utils.h:281
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
const char * callee_id_number
Definition: switch_caller.h:89
const char * caller_id_name
Definition: switch_caller.h:79
#define MESSAGE_STAMP_FFL(_m)
Definition: switch_core.h:173
const char * caller_id_number
Definition: switch_caller.h:81
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
switch_caller_profile_t * switch_channel_get_caller_profile(switch_channel_t *channel)
Retrieve the given channel's caller profile.
const char * callee_id_name
Definition: switch_caller.h:87
static switch_status_t signal_bridge_on_hangup ( switch_core_session_t session)
static

Definition at line 1227 of file switch_ivr_bridge.c.

References CF_ANSWERED, CF_BRIDGE_ORIGINATOR, CF_INTERCEPT, CF_INTERCEPTED, CS_EXECUTE, sb_on_dtmf(), SWITCH_BRIDGE_VARIABLE, switch_channel_clear_flag_recursive(), switch_channel_event_set_data(), switch_channel_get_cause(), switch_channel_get_private(), switch_channel_get_variable, switch_channel_handle_cause(), switch_channel_hangup, switch_channel_set_flag, switch_channel_set_private(), switch_channel_set_state, switch_channel_set_variable, switch_channel_test_flag(), switch_channel_up_nosig, switch_core_session_get_channel(), switch_core_session_get_uuid(), switch_core_session_locate, switch_core_session_rwunlock(), switch_event_add_header_string(), switch_event_add_presence_data_cols(), SWITCH_EVENT_CHANNEL_UNBRIDGE, switch_event_create, switch_event_fire, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, switch_ivr_park_session(), SWITCH_PARK_AFTER_BRIDGE_VARIABLE, SWITCH_SIGNAL_BRIDGE_VARIABLE, SWITCH_STACK_BOTTOM, SWITCH_STATUS_SUCCESS, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE, switch_true(), transfer_after_bridge(), and zstr.

1228 {
1229  const char *uuid;
1231  switch_core_session_t *other_session;
1232  switch_event_t *event;
1233 
1236  }
1237 
1238  if (switch_channel_get_private(channel, "__bridge_term_key")) {
1239  switch_core_event_hook_remove_recv_dtmf(session, sb_on_dtmf);
1240  switch_channel_set_private(channel, "__bridge_term_key", NULL);
1241  }
1242 
1244 
1245  if (uuid && (other_session = switch_core_session_locate(uuid))) {
1246  switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
1247  const char *sbv = switch_channel_get_variable(other_channel, SWITCH_SIGNAL_BRIDGE_VARIABLE);
1248  const char *var;
1249 
1250  if (!zstr(sbv) && !strcmp(sbv, switch_core_session_get_uuid(session))) {
1251  int hup = 1;
1252 
1255  switch_channel_set_variable(other_channel, "call_uuid", switch_core_session_get_uuid(other_session));
1256 
1257  if (switch_channel_up_nosig(other_channel)) {
1259  switch_ivr_park_session(other_session);
1260  hup = 0;
1261  } else if ((var = switch_channel_get_variable(other_channel, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE))) {
1262  transfer_after_bridge(other_session, var);
1263  hup = 0;
1264  }
1265 
1266  if (hup) {
1267  if (switch_channel_test_flag(other_channel, CF_BRIDGE_ORIGINATOR)) {
1268  if (switch_channel_test_flag(channel, CF_ANSWERED) &&
1270 
1271  if (switch_channel_test_flag(channel, CF_INTERCEPTED)) {
1272  switch_channel_set_flag(other_channel, CF_INTERCEPT);
1273  }
1274  switch_channel_hangup(other_channel, switch_channel_get_cause(channel));
1275  } else {
1276  if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
1277  switch_channel_handle_cause(other_channel, switch_channel_get_cause(channel));
1278  }
1279  switch_channel_set_state(other_channel, CS_EXECUTE);
1280  }
1281  } else {
1282  switch_channel_hangup(other_channel, switch_channel_get_cause(channel));
1283  }
1284  }
1285  }
1286  }
1287 
1292  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", uuid);
1293  switch_event_add_presence_data_cols(other_channel, event, "Bridge-B-PD-");
1294  switch_channel_event_set_data(channel, event);
1295  switch_event_fire(&event);
1296  }
1297  }
1298 
1299  switch_core_session_rwunlock(other_session);
1300  } else {
1305  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", uuid);
1306  switch_channel_event_set_data(channel, event);
1307  switch_event_fire(&event);
1308  }
1309  }
1310  }
1311 
1312  return SWITCH_STATUS_SUCCESS;
1313 }
#define SWITCH_SIGNAL_BRIDGE_VARIABLE
Definition: switch_types.h:201
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
void switch_event_add_presence_data_cols(switch_channel_t *channel, switch_event_t *event, const char *prefix)
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
Representation of an event.
Definition: switch_event.h:80
static switch_status_t sb_on_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf, switch_dtmf_direction_t direction)
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
#define zstr(x)
Definition: switch_utils.h:281
#define SWITCH_PARK_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:217
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:216
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
#define SWITCH_BRIDGE_VARIABLE
Definition: switch_types.h:199
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
void switch_ivr_park_session(switch_core_session_t *session)
Definition: switch_ivr.c:3411
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
static void transfer_after_bridge(switch_core_session_t *session, const char *where)
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
#define switch_channel_set_flag(_c, _f)
void switch_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
#define switch_channel_up_nosig(_channel)
#define switch_channel_set_variable(_channel, _var, _val)
#define SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:219
switch_call_cause_t switch_channel_get_cause(_In_ switch_channel_t *channel)
return the cause code for a given channel
void switch_channel_handle_cause(switch_channel_t *channel, switch_call_cause_t cause)
static switch_status_t signal_bridge_on_hibernate ( switch_core_session_t session)
static

Definition at line 1155 of file switch_ivr_bridge.c.

References CF_BRIDGE_ORIGINATOR, CF_BROADCAST, CS_HIBERNATE, DIGIT_TARGET_PEER, DIGIT_TARGET_SELF, switch_core_session_message::from, hanguphook(), switch_core_session_message::message_id, sb_on_dtmf(), switch_core_session_message::string_arg, switch_assert, SWITCH_BRIDGE_VARIABLE, switch_channel_event_set_data(), switch_channel_get_name(), switch_channel_get_state(), switch_channel_get_variable, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_bridge_time(), switch_channel_set_private(), switch_channel_set_variable, switch_channel_test_flag(), switch_core_session_get_channel(), switch_core_session_get_dmachine(), switch_core_session_get_uuid(), switch_core_session_locate, switch_core_session_receive_message, switch_core_session_rwunlock(), switch_core_session_strdup, switch_event_add_header_string(), switch_event_add_presence_data_cols(), SWITCH_EVENT_CHANNEL_BRIDGE, switch_event_create, switch_event_fire, switch_ivr_dmachine_ping(), switch_ivr_parse_all_messages(), SWITCH_LAST_BRIDGE_VARIABLE, SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_MESSAGE_INDICATE_BRIDGE, SWITCH_SIGNAL_BRIDGE_VARIABLE, SWITCH_STACK_BOTTOM, SWITCH_STATUS_SUCCESS, and switch_yield.

1156 {
1157  switch_channel_t *channel = NULL;
1158  const char *key;
1159  switch_core_session_message_t msg = { 0 };
1160  switch_event_t *event = NULL;
1161  switch_ivr_dmachine_t *dmachine[2] = { 0 };
1162 
1163  channel = switch_core_session_get_channel(session);
1164  switch_assert(channel != NULL);
1165 
1167  msg.from = __FILE__;
1169 
1170  switch_core_event_hook_add_state_change(session, hanguphook);
1171 
1172  switch_core_session_receive_message(session, &msg);
1173 
1174  if ((key = switch_channel_get_variable(channel, "bridge_terminate_key"))) {
1175  switch_channel_set_private(channel, "__bridge_term_key", switch_core_session_strdup(session, key));
1176  switch_core_event_hook_add_recv_dtmf(session, sb_on_dtmf);
1177  }
1178 
1181 
1183 
1184 
1187  switch_core_session_t *other_session;
1188 
1190  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", msg.string_arg);
1191  switch_channel_event_set_data(channel, event);
1192  if ((other_session = switch_core_session_locate(msg.string_arg))) {
1193  switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
1194 
1195  switch_channel_set_bridge_time(other_channel);
1196 
1197  switch_event_add_presence_data_cols(other_channel, event, "Bridge-B-PD-");
1198  switch_core_session_rwunlock(other_session);
1199  }
1200  switch_event_fire(&event);
1201  }
1202  }
1203 
1204  if ((dmachine[0] = switch_core_session_get_dmachine(session, DIGIT_TARGET_SELF)) ||
1205  (dmachine[1] = switch_core_session_get_dmachine(session, DIGIT_TARGET_PEER))) {
1207  "%s not hibernating due to active digit parser, semi-hibernation engaged.\n", switch_channel_get_name(channel));
1208 
1209  while(switch_channel_ready(channel) && switch_channel_get_state(channel) == CS_HIBERNATE) {
1210  if (!switch_channel_test_flag(channel, CF_BROADCAST)) {
1211  if (dmachine[0]) {
1212  switch_ivr_dmachine_ping(dmachine[0], NULL);
1213  }
1214  if (dmachine[1]) {
1215  switch_ivr_dmachine_ping(dmachine[1], NULL);
1216  }
1217  }
1218  switch_yield(20000);
1220  }
1221  }
1222 
1223 
1224  return SWITCH_STATUS_SUCCESS;
1225 }
#define SWITCH_SIGNAL_BRIDGE_VARIABLE
Definition: switch_types.h:201
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define SWITCH_LAST_BRIDGE_VARIABLE
Definition: switch_types.h:200
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
void switch_channel_set_bridge_time(switch_channel_t *channel)
void switch_event_add_presence_data_cols(switch_channel_t *channel, switch_event_t *event, const char *prefix)
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
static switch_status_t sb_on_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf, switch_dtmf_direction_t direction)
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
static switch_status_t hanguphook(switch_core_session_t *session)
#define SWITCH_BRIDGE_VARIABLE
Definition: switch_types.h:199
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
switch_ivr_dmachine_t * switch_core_session_get_dmachine(switch_core_session_t *session, switch_digit_action_target_t target)
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
switch_status_t switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
#define switch_assert(expr)
#define switch_channel_set_variable(_channel, _var, _val)
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
switch_status_t switch_ivr_parse_all_messages(switch_core_session_t *session)
Definition: switch_ivr.c:801
switch_status_t switch_ivr_multi_threaded_bridge ( switch_core_session_t session,
switch_core_session_t peer_session,
switch_input_callback_function_t  input_callback,
void *  session_data,
void *  peer_session_data 
)

Definition at line 1422 of file switch_ivr_bridge.c.

References abort_call(), audio_bridge_thread(), switch_ivr_bridge_data::b_uuid, CF_ANSWERED, CF_BRIDGE_ORIGINATOR, CF_BRIDGED, CF_BROADCAST, CF_EARLY_MEDIA, CF_INNER_BRIDGE, CF_INTERCEPT, CF_INTERCEPTED, CF_MEDIA_BRIDGE_TTL, CF_PROXY_MODE, CF_REDIRECT, CF_RESET, CF_RING_READY, CF_TRANSFER, CF_XFER_ZOMBIE, check_bridge_export(), cJSON_Delete(), cJSON_PrintUnformatted(), switch_ivr_bridge_data::clean_exit, CS_CONSUME_MEDIA, CS_DESTROY, CS_EXCHANGE_MEDIA, CS_EXECUTE, CS_HANGUP, CS_PARK, CS_RESET, CS_ROUTING, CS_SOFT_EXECUTE, switch_core_session_message::from, switch_ivr_bridge_data::input_callback, switch_core_session_message::message_id, switch_ivr_bridge_data::other_leg_data, switch_ivr_bridge_data::session, switch_ivr_bridge_data::session_data, switch_ivr_bridge_data::stream_id, switch_core_session_message::string_arg, SWITCH_BRIDGE_CHANNEL_VARIABLE, SWITCH_BRIDGE_HANGUP_CAUSE_VARIABLE, SWITCH_BRIDGE_UUID_VARIABLE, SWITCH_BRIDGE_VARIABLE, SWITCH_CAUSE_ALLOTTED_TIMEOUT, SWITCH_CAUSE_NO_ANSWER, SWITCH_CAUSE_NONE, SWITCH_CAUSE_NORMAL_CLEARING, switch_channel_add_state_handler(), switch_channel_answer, switch_channel_audio_sync, switch_channel_cause2str(), switch_channel_clear_flag(), switch_channel_clear_flag_recursive(), switch_channel_down_nosig, switch_channel_event_set_data(), switch_channel_get_cause(), switch_channel_get_name(), switch_channel_get_state(), switch_channel_get_variable, switch_channel_handle_cause(), switch_channel_hangup, switch_channel_media_ready, switch_channel_pass_callee_id(), switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_bridge_time(), switch_channel_set_flag, switch_channel_set_flag_recursive(), switch_channel_set_private(), switch_channel_set_state, switch_channel_set_variable, switch_channel_set_variable_name_printf(), switch_channel_stop_broadcast, switch_channel_test_flag(), switch_channel_wait_for_flag(), switch_channel_wait_for_state(), switch_cond_next(), SWITCH_COPY_JSON_CDR_VARIABLE, switch_copy_string(), SWITCH_COPY_XML_CDR_VARIABLE, switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_get_uuid(), switch_core_session_read_lock(), switch_core_session_receive_message, switch_core_session_rwunlock(), switch_core_session_strdup, switch_event_add_header_string(), switch_event_add_presence_data_cols(), SWITCH_EVENT_CHANNEL_BRIDGE, SWITCH_EVENT_CHANNEL_UNBRIDGE, switch_event_create, switch_event_fire, SWITCH_FALSE, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, switch_ivr_generate_json_cdr(), switch_ivr_generate_xml_cdr(), switch_ivr_park_session(), switch_ivr_parse_all_events(), switch_ivr_parse_all_messages(), switch_ivr_session_transfer(), switch_ivr_signal_bridge(), switch_ivr_wait_for_answer(), SWITCH_LAST_BRIDGE_VARIABLE, SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_MESSAGE_INDICATE_BRIDGE, SWITCH_MESSAGE_INDICATE_UNBRIDGE, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, SWITCH_PARK_AFTER_EARLY_BRIDGE_VARIABLE, switch_safe_free, SWITCH_SIGNAL_BOND_VARIABLE, SWITCH_STACK_BOTTOM, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE, SWITCH_TRANSFER_AFTER_EARLY_BRIDGE_VARIABLE, SWITCH_TRUE, switch_true(), switch_xml_free(), switch_xml_toxml(), and transfer_after_bridge().

Referenced by uuid_bridge_on_soft_execute().

1426 {
1427  switch_ivr_bridge_data_t *a_leg = switch_core_session_alloc(session, sizeof(*a_leg));
1428  switch_ivr_bridge_data_t *b_leg = switch_core_session_alloc(peer_session, sizeof(*b_leg));
1429  switch_channel_t *caller_channel = switch_core_session_get_channel(session);
1430  switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
1431  int stream_id = 0;
1434  switch_event_t *event;
1435  int br = 0;
1436  int inner_bridge = switch_channel_test_flag(caller_channel, CF_INNER_BRIDGE);
1437  const char *var;
1438  switch_call_cause_t cause;
1439  switch_core_session_message_t msg = { 0 };
1440 
1441  if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
1442  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Call has no media... Redirecting to signal bridge.\n");
1443  return switch_ivr_signal_bridge(session, peer_session);
1444  }
1445 
1446  check_bridge_export(caller_channel, peer_channel);
1447 
1450 
1453 
1454  switch_channel_audio_sync(caller_channel);
1455  switch_channel_audio_sync(peer_channel);
1456 
1457  b_leg->session = peer_session;
1458  switch_copy_string(b_leg->b_uuid, switch_core_session_get_uuid(session), sizeof(b_leg->b_uuid));
1459  b_leg->stream_id = stream_id;
1460  b_leg->input_callback = input_callback;
1461  b_leg->session_data = peer_session_data;
1462  b_leg->clean_exit = 0;
1463  b_leg->other_leg_data = a_leg;
1464 
1465  a_leg->session = session;
1466  switch_copy_string(a_leg->b_uuid, switch_core_session_get_uuid(peer_session), sizeof(a_leg->b_uuid));
1467  a_leg->stream_id = stream_id;
1468  a_leg->input_callback = input_callback;
1469  a_leg->session_data = session_data;
1470  a_leg->clean_exit = 0;
1471  a_leg->other_leg_data = b_leg;
1472 
1474 
1475  if (switch_channel_test_flag(peer_channel, CF_ANSWERED) && !switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
1476  switch_channel_pass_callee_id(peer_channel, caller_channel);
1477  switch_channel_answer(caller_channel);
1478  }
1479 
1480  if (switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA) ||
1481  switch_channel_test_flag(peer_channel, CF_RING_READY)) {
1482  const char *app, *data;
1483 
1484  if (!switch_channel_ready(caller_channel)) {
1485  abort_call(caller_channel, peer_channel);
1486  goto done;
1487  }
1488 
1490 
1491  switch_channel_set_variable(peer_channel, "call_uuid", switch_core_session_get_uuid(session));
1492 
1493  switch_channel_set_bridge_time(caller_channel);
1494  switch_channel_set_bridge_time(peer_channel);
1495 
1498  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", switch_core_session_get_uuid(peer_session));
1499  switch_channel_event_set_data(caller_channel, event);
1500  switch_event_add_presence_data_cols(peer_channel, event, "Bridge-B-PD-");
1501  switch_event_fire(&event);
1502  br = 1;
1503  }
1504 
1510 
1511  if (!switch_channel_ready(caller_channel)) {
1512  abort_call(caller_channel, peer_channel);
1513  switch_core_session_rwunlock(peer_session);
1514  goto done;
1515  }
1516 
1517  if (!switch_channel_media_ready(caller_channel) ||
1518  (!switch_channel_test_flag(peer_channel, CF_ANSWERED) && !switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA))) {
1519  if ((status = switch_ivr_wait_for_answer(session, peer_session)) != SWITCH_STATUS_SUCCESS || !switch_channel_ready(caller_channel)) {
1520  switch_channel_state_t w_state = switch_channel_get_state(caller_channel);
1522  if (w_state < CS_HANGUP && w_state != CS_ROUTING && w_state != CS_PARK &&
1523  !switch_channel_test_flag(caller_channel, CF_REDIRECT) && !switch_channel_test_flag(caller_channel, CF_TRANSFER) &&
1524  w_state != CS_EXECUTE) {
1525  const char *ext = switch_channel_get_variable(peer_channel, "original_destination_number");
1526  if (!ext) {
1527  ext = switch_channel_get_variable(peer_channel, "destination_number");
1528  }
1529 
1530  if (ext) {
1531  switch_ivr_session_transfer(session, ext, NULL, NULL);
1532  } else {
1534  }
1535  }
1536  abort_call(caller_channel, peer_channel);
1537  switch_core_session_rwunlock(peer_session);
1538  goto done;
1539  }
1540  }
1541 
1542  if (switch_channel_test_flag(peer_channel, CF_ANSWERED) && !switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
1543  switch_channel_answer(caller_channel);
1544  }
1545 
1546  switch_channel_wait_for_flag(peer_channel, CF_BROADCAST, SWITCH_FALSE, 10000, caller_channel);
1547  switch_ivr_parse_all_events(peer_session);
1548  switch_ivr_parse_all_events(session);
1549 
1551  msg.from = __FILE__;
1553 
1554  if (switch_core_session_receive_message(peer_session, &msg) != SWITCH_STATUS_SUCCESS) {
1555  status = SWITCH_STATUS_FALSE;
1556  abort_call(caller_channel, peer_channel);
1557  switch_core_session_rwunlock(peer_session);
1558  goto done;
1559  }
1560 
1563  status = SWITCH_STATUS_FALSE;
1564  abort_call(caller_channel, peer_channel);
1565  switch_core_session_rwunlock(peer_session);
1566  goto done;
1567  }
1568 
1575 
1576  if ((app = switch_channel_get_variable(caller_channel, "bridge_pre_execute_aleg_app"))) {
1577  switch_channel_set_variable(caller_channel, "bridge_pre_execute_app", app);
1578 
1579  if ((data = switch_channel_get_variable(caller_channel, "bridge_pre_execute_aleg_data"))) {
1580  switch_channel_set_variable(caller_channel, "bridge_pre_execute_data", data);
1581  }
1582  }
1583 
1584  if ((app = switch_channel_get_variable(caller_channel, "bridge_pre_execute_bleg_app"))) {
1585  switch_channel_set_variable(peer_channel, "bridge_pre_execute_app", app);
1586 
1587  if ((data = switch_channel_get_variable(caller_channel, "bridge_pre_execute_bleg_data"))) {
1588  switch_channel_set_variable(peer_channel, "bridge_pre_execute_data", data);
1589  }
1590 
1591  }
1592 
1593  switch_channel_set_private(peer_channel, "_bridge_", b_leg);
1595 
1596  audio_bridge_thread(NULL, (void *) a_leg);
1597 
1599 
1600  switch_channel_stop_broadcast(peer_channel);
1601 
1602 
1603  while (switch_channel_get_state(peer_channel) == CS_EXCHANGE_MEDIA) {
1605  switch_cond_next();
1606  }
1607 
1608  if (inner_bridge) {
1609  if (switch_channel_ready(caller_channel)) {
1610  switch_channel_set_flag(caller_channel, CF_BRIDGED);
1611  }
1612 
1613  if (switch_channel_ready(peer_channel)) {
1614  switch_channel_set_flag(peer_channel, CF_BRIDGED);
1615  }
1616  }
1617 
1618  if ((cause = switch_channel_get_cause(caller_channel))) {
1620  }
1621 
1622  if ((cause = switch_channel_get_cause(peer_channel))) {
1624  }
1625 
1626  if (switch_channel_down_nosig(peer_channel)) {
1629 
1630  if (copy_xml_cdr || copy_json_cdr) {
1631  char *cdr_text = NULL;
1632 
1633  switch_channel_wait_for_state(peer_channel, caller_channel, CS_DESTROY);
1634 
1635  if (copy_xml_cdr) {
1636  switch_xml_t cdr = NULL;
1637 
1638  if (switch_ivr_generate_xml_cdr(peer_session, &cdr) == SWITCH_STATUS_SUCCESS) {
1639  cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE);
1640  switch_xml_free(cdr);
1641  }
1642  }
1643  if (copy_json_cdr) {
1644  cJSON *cdr = NULL;
1645 
1646  if (switch_ivr_generate_json_cdr(peer_session, &cdr, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
1647  cdr_text = cJSON_PrintUnformatted(cdr);
1648  cJSON_Delete(cdr);
1649  }
1650  }
1651 
1652  if (cdr_text) {
1653  switch_channel_set_variable(caller_channel, "b_leg_cdr", cdr_text);
1654  switch_channel_set_variable_name_printf(caller_channel, cdr_text, "b_leg_cdr_%s", switch_core_session_get_uuid(peer_session));
1655  switch_safe_free(cdr_text);
1656  }
1657  }
1658 
1659  }
1660 
1661  switch_core_session_rwunlock(peer_session);
1662 
1663  } else {
1664  status = SWITCH_STATUS_FALSE;
1665  }
1666  } else {
1667  status = SWITCH_STATUS_FALSE;
1668  }
1669 
1670  if (status != SWITCH_STATUS_SUCCESS) {
1671  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Bridge Failed %s->%s\n",
1672  switch_channel_get_name(caller_channel), switch_channel_get_name(peer_channel)
1673  );
1675  }
1676 
1677  done:
1678 
1679  switch_channel_set_variable(peer_channel, "call_uuid", switch_core_session_get_uuid(peer_session));
1680 
1683  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", switch_core_session_get_uuid(peer_session));
1684  switch_channel_event_set_data(caller_channel, event);
1685  switch_event_add_presence_data_cols(peer_channel, event, "Bridge-B-PD-");
1686  switch_event_fire(&event);
1687  }
1688 
1690  msg.from = __FILE__;
1692  switch_core_session_receive_message(peer_session, &msg);
1693 
1695  switch_core_session_receive_message(session, &msg);
1696 
1697  state = switch_channel_get_state(caller_channel);
1698 
1699  if (!switch_channel_test_flag(caller_channel, CF_TRANSFER) && !switch_channel_test_flag(caller_channel, CF_REDIRECT) &&
1700  !switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE) && !a_leg->clean_exit && !inner_bridge) {
1701  switch_call_cause_t cause = switch_channel_get_cause(peer_channel);
1702  const char *hup = switch_channel_get_variable(caller_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE);
1703  int explicit = 0;
1704  int answered = 0;
1705  int early = 0;
1706 
1707  if (cause == SWITCH_CAUSE_NONE) {
1709  }
1710 
1711  if (hup) {
1712  explicit = !strcasecmp(hup, "explicit");
1713  }
1714 
1715  if (cause && !switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
1716  switch_channel_handle_cause(caller_channel, cause);
1717  }
1718 
1719  if (explicit) {
1720  if (switch_channel_test_flag(peer_channel, CF_INTERCEPTED)) {
1721  switch_channel_set_flag(peer_channel, CF_INTERCEPT);
1722  }
1723  switch_channel_hangup(caller_channel, cause);
1724  }
1725 
1726  answered = switch_channel_test_flag(peer_channel, CF_ANSWERED);
1727  early = switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA);
1728 
1729  if ((state != CS_EXECUTE && state != CS_SOFT_EXECUTE && state != CS_PARK && state != CS_ROUTING) || ((answered || early) && state < CS_HANGUP)) {
1730 
1731  if (!switch_channel_test_flag(caller_channel, CF_TRANSFER)) {
1732 
1733  if ((answered && switch_true(switch_channel_get_variable(caller_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE))) ||
1735  switch_ivr_park_session(session);
1736  } else if ((answered && (var = switch_channel_get_variable(caller_channel, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE))) ||
1738  transfer_after_bridge(session, var);
1739  } else if (answered) {
1740  if (switch_true(hup)) {
1741  if (switch_channel_test_flag(peer_channel, CF_INTERCEPTED)) {
1742  switch_channel_set_flag(peer_channel, CF_INTERCEPT);
1743  }
1744  switch_channel_hangup(caller_channel, cause);
1745  }
1746  }
1747  }
1748  }
1749  }
1750 
1751  if (switch_channel_test_flag(caller_channel, CF_REDIRECT)) {
1752  if (switch_channel_test_flag(caller_channel, CF_RESET)) {
1753  switch_channel_clear_flag(caller_channel, CF_RESET);
1754  } else {
1755  state = switch_channel_get_state(caller_channel);
1756  if (!(state == CS_RESET || state == CS_PARK || state == CS_ROUTING)) {
1757  switch_channel_set_state(caller_channel, CS_RESET);
1758  }
1759  }
1760  }
1761 
1762  return status;
1763 }
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
#define switch_channel_answer(channel)
Answer a channel (initiate/acknowledge a successful connection)
void switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
#define SWITCH_CHANNEL_SESSION_LOG(x)
char * switch_xml_toxml(_In_ switch_xml_t xml, _In_ switch_bool_t prn_header)
Converts an switch_xml structure back to xml in html format. Returns a string of html data that \ mus...
#define SWITCH_LAST_BRIDGE_VARIABLE
Definition: switch_types.h:200
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
switch_status_t switch_channel_set_variable_name_printf(switch_channel_t *channel, const char *val, const char *fmt,...)
#define SWITCH_COPY_XML_CDR_VARIABLE
Definition: switch_types.h:138
switch_core_session_t * session
#define SWITCH_PARK_AFTER_EARLY_BRIDGE_VARIABLE
Definition: switch_types.h:218
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
const char * switch_channel_cause2str(_In_ switch_call_cause_t cause)
return a cause string for a given cause
switch_status_t switch_ivr_wait_for_answer(switch_core_session_t *session, switch_core_session_t *peer_session)
#define switch_channel_stop_broadcast(_channel)
void switch_channel_set_bridge_time(switch_channel_t *channel)
void switch_event_add_presence_data_cols(switch_channel_t *channel, switch_event_t *event, const char *prefix)
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
switch_bool_t
Definition: switch_types.h:405
Representation of an event.
Definition: switch_event.h:80
struct switch_ivr_bridge_data * other_leg_data
#define switch_channel_ready(_channel)
switch_status_t switch_core_session_read_lock(_In_ switch_core_session_t *session)
Acquire a read lock on the session.
#define switch_channel_media_ready(_channel)
A representation of an XML tree.
Definition: switch_xml.h:76
switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session)
Parse all commands from an event.
Definition: switch_ivr.c:867
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
#define SWITCH_COPY_JSON_CDR_VARIABLE
Definition: switch_types.h:139
#define SWITCH_PARK_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:217
switch_status_t switch_ivr_session_transfer(_In_ switch_core_session_t *session, const char *extension, const char *dialplan, const char *context)
Transfer an existing session to another location.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:216
void switch_channel_wait_for_state(switch_channel_t *channel, switch_channel_t *other_channel, switch_channel_state_t want_state)
#define switch_channel_audio_sync(_c)
char b_uuid[SWITCH_UUID_FORMATTED_LENGTH+1]
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
#define SWITCH_BRIDGE_HANGUP_CAUSE_VARIABLE
Definition: switch_types.h:127
#define SWITCH_BRIDGE_UUID_VARIABLE
Definition: switch_types.h:182
#define switch_channel_down_nosig(_channel)
#define SWITCH_TRANSFER_AFTER_EARLY_BRIDGE_VARIABLE
Definition: switch_types.h:220
void switch_cond_next(void)
Definition: switch_time.c:638
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
#define SWITCH_BRIDGE_VARIABLE
Definition: switch_types.h:199
switch_call_cause_t
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
switch_input_callback_function_t input_callback
void switch_ivr_park_session(switch_core_session_t *session)
Definition: switch_ivr.c:3411
switch_channel_state_t
Channel States (these are the defaults, CS_SOFT_EXECUTE, CS_EXCHANGE_MEDIA, and CS_CONSUME_MEDIA are ...
switch_status_t switch_ivr_generate_json_cdr(switch_core_session_t *session, cJSON **json_cdr, switch_bool_t urlencode)
Generate an JSON CDR report.
Definition: switch_ivr.c:3177
switch_status_t
Common return values.
static void check_bridge_export(switch_channel_t *channel, switch_channel_t *peer_channel)
static void transfer_after_bridge(switch_core_session_t *session, const char *where)
#define SWITCH_SIGNAL_BOND_VARIABLE
Definition: switch_types.h:202
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
static void abort_call(switch_channel_t *caller_channel, switch_channel_t *peer_channel)
#define switch_channel_set_flag(_c, _f)
static const switch_state_handler_table_t audio_bridge_peer_state_handlers
int switch_channel_add_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
add a state handler table to a given channel
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
void switch_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
switch_status_t switch_channel_wait_for_flag(switch_channel_t *channel, switch_channel_flag_t want_flag, switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
switch_status_t switch_ivr_signal_bridge(switch_core_session_t *session, switch_core_session_t *peer_session)
Bridge Signalling from one session to another.
#define switch_channel_set_variable(_channel, _var, _val)
switch_status_t switch_ivr_generate_xml_cdr(switch_core_session_t *session, switch_xml_t *xml_cdr)
Generate an XML CDR report.
Definition: switch_ivr.c:2713
#define SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:219
void cJSON_Delete(cJSON *c)
Definition: switch_json.c:93
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
switch_status_t switch_channel_pass_callee_id(switch_channel_t *channel, switch_channel_t *other_channel)
char * cJSON_PrintUnformatted(cJSON *item)
Definition: switch_json.c:285
#define SWITCH_BRIDGE_CHANNEL_VARIABLE
Definition: switch_types.h:180
switch_call_cause_t switch_channel_get_cause(_In_ switch_channel_t *channel)
return the cause code for a given channel
static void * audio_bridge_thread(switch_thread_t *thread, void *obj)
switch_status_t switch_ivr_parse_all_messages(switch_core_session_t *session)
Definition: switch_ivr.c:801
void switch_channel_handle_cause(switch_channel_t *channel, switch_call_cause_t cause)
static void transfer_after_bridge ( switch_core_session_t session,
const char *  where 
)
static

Definition at line 822 of file switch_ivr_bridge.c.

References SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_variable, switch_core_session_get_channel(), switch_core_session_strdup, switch_ivr_session_transfer(), SWITCH_LOG_ERROR, switch_log_printf(), switch_separate_string(), SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE, and zstr.

Referenced by audio_bridge_on_exchange_media(), signal_bridge_on_hangup(), and switch_ivr_multi_threaded_bridge().

823 {
824  int argc;
825  char *argv[4] = { 0 };
826  char *mydata;
827 
829 
830  if (!zstr(where) && (mydata = switch_core_session_strdup(session, where))) {
831  if ((argc = switch_separate_string(mydata, ':', argv, (sizeof(argv) / sizeof(argv[0])))) >= 1) {
832  switch_ivr_session_transfer(session, argv[0], argv[1], argv[2]);
833  } else {
834  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No extension specified.\n");
835  }
836  }
837 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define zstr(x)
Definition: switch_utils.h:281
switch_status_t switch_ivr_session_transfer(_In_ switch_core_session_t *session, const char *extension, const char *dialplan, const char *context)
Transfer an existing session to another location.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
#define switch_channel_set_variable(_channel, _var, _val)
#define SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE
Definition: switch_types.h:219
static switch_status_t uuid_bridge_on_hibernate ( switch_core_session_t session)
static

Definition at line 962 of file switch_ivr_bridge.c.

References CS_RESET, switch_channel_set_state, switch_core_session_get_channel(), and SWITCH_STATUS_FALSE.

963 {
965  return SWITCH_STATUS_FALSE;
966 }
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
static switch_status_t uuid_bridge_on_reset ( switch_core_session_t session)
static

Definition at line 945 of file switch_ivr_bridge.c.

References CF_ORIGINATING, CF_UUID_BRIDGE_ORIGINATOR, cleanup_proxy_mode_b(), CS_SOFT_EXECUTE, switch_channel_clear_flag(), switch_channel_get_name(), SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_state, switch_channel_test_flag(), switch_core_session_get_channel(), SWITCH_LOG_DEBUG, switch_log_printf(), and SWITCH_STATUS_SUCCESS.

946 {
948 
950 
952 
953  cleanup_proxy_mode_b(session);
954 
957  }
958 
959  return SWITCH_STATUS_SUCCESS;
960 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
static void cleanup_proxy_mode_b(switch_core_session_t *session)
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
static switch_status_t uuid_bridge_on_soft_execute ( switch_core_session_t session)
static

Definition at line 968 of file switch_ivr_bridge.c.

References CF_REDIRECT, CF_TRANSFER, CF_UUID_BRIDGE_ORIGINATOR, CS_EXECUTE, CS_HANGUP, CS_PARK, CS_RESET, CS_ROUTING, CS_SOFT_EXECUTE, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, SWITCH_CAUSE_ORIGINATOR_CANCEL, switch_channel_clear_flag(), switch_channel_clear_state_handler(), switch_channel_down, switch_channel_down_nosig, switch_channel_event_set_data(), switch_channel_get_name(), switch_channel_get_running_state(), switch_channel_get_state(), switch_channel_get_variable, switch_channel_hangup, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_state, switch_channel_set_variable, switch_channel_test_flag(), switch_core_session_get_channel(), switch_core_session_get_uuid(), switch_core_session_locate, switch_core_session_reset(), switch_core_session_rwunlock(), switch_event_add_header_string(), SWITCH_EVENT_CHANNEL_EXECUTE, switch_event_create, switch_event_fire, switch_ivr_multi_threaded_bridge(), switch_ivr_park_session(), switch_ivr_session_transfer(), switch_ivr_wait_for_answer(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_STACK_BOTTOM, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, SWITCH_TRUE, switch_true(), SWITCH_UUID_BRIDGE, and switch_yield.

969 {
971  switch_core_session_t *other_session = NULL;
972  const char *other_uuid = NULL;
973 
974  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CUSTOM SOFT_EXECUTE\n", switch_channel_get_name(channel));
976 
978  return SWITCH_STATUS_SUCCESS;
979  }
980 
981  if ((other_uuid = switch_channel_get_variable(channel, SWITCH_UUID_BRIDGE)) && (other_session = switch_core_session_locate(other_uuid))) {
982  switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
983  switch_event_t *event;
984  int ready_a, ready_b;
985  switch_channel_state_t state, running_state;
986  int max = 1000, loops = max;
987 
989 
990  for (;;) {
991  state = switch_channel_get_state(other_channel);
992  running_state = switch_channel_get_running_state(other_channel);
993 
994  if (switch_channel_down_nosig(other_channel) || switch_channel_down(channel)) {
995  break;
996  }
997 
998  if (state < CS_HANGUP && state == running_state) {
999 
1000  if (--loops < 1) {
1003  }
1004 
1005  if (running_state == CS_RESET) {
1006  switch_channel_set_state(other_channel, CS_SOFT_EXECUTE);
1007  }
1008 
1009  if (running_state == CS_SOFT_EXECUTE) {
1010 
1012  goto done;
1013  } else {
1014  break;
1015  }
1016  }
1017 
1018  } else {
1019  loops = max;
1020  }
1021 
1022  switch_yield(20000);
1023  }
1024 
1026 
1027  if (switch_ivr_wait_for_answer(session, other_session) != SWITCH_STATUS_SUCCESS) {
1028  if (switch_true(switch_channel_get_variable(channel, "uuid_bridge_continue_on_cancel"))) {
1030  } else if (switch_true(switch_channel_get_variable(channel, "uuid_bridge_park_on_cancel"))) {
1031  switch_ivr_park_session(session);
1032  } else if (!switch_channel_test_flag(channel, CF_TRANSFER)) {
1034  }
1035  goto done;
1036  }
1037 
1038  ready_a = switch_channel_ready(channel);
1039  ready_b = switch_channel_ready(other_channel);
1040 
1041  if (!ready_a || !ready_b) {
1042  if (!ready_a) {
1044  }
1045 
1046  if (!ready_b) {
1047  const char *cid = switch_channel_get_variable(other_channel, "rdnis");
1048  if (ready_a && cid) {
1049  switch_ivr_session_transfer(session, cid, NULL, NULL);
1050  } else {
1052  }
1053  }
1054  goto done;
1055  }
1056 
1057  /* fire events that will change the data table from "show channels" */
1059  switch_channel_event_set_data(channel, event);
1060  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", "uuid_bridge");
1061  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-Data", switch_core_session_get_uuid(other_session));
1062  switch_event_fire(&event);
1063  }
1064 
1066  switch_channel_event_set_data(other_channel, event);
1067  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", "uuid_bridge");
1069  switch_event_fire(&event);
1070  }
1071 
1072  switch_ivr_multi_threaded_bridge(session, other_session, NULL, NULL, NULL);
1073 
1074  state = switch_channel_get_state(channel);
1075  if (!switch_channel_test_flag(channel, CF_TRANSFER) &&
1076  !switch_channel_test_flag(channel, CF_REDIRECT) && state < CS_HANGUP && state != CS_ROUTING && state != CS_PARK) {
1078  }
1079  } else {
1081  }
1082 
1083  done:
1084 
1085  if (other_session) {
1086  switch_core_session_rwunlock(other_session);
1087  other_session = NULL;
1088  }
1089 
1091 
1092  return SWITCH_STATUS_FALSE;
1093 }
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
#define SWITCH_CHANNEL_SESSION_LOG(x)
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
switch_status_t switch_ivr_wait_for_answer(switch_core_session_t *session, switch_core_session_t *peer_session)
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
static const switch_state_handler_table_t uuid_bridge_state_handlers
switch_channel_state_t switch_channel_get_running_state(switch_channel_t *channel)
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
switch_status_t switch_ivr_session_transfer(_In_ switch_core_session_t *session, const char *extension, const char *dialplan, const char *context)
Transfer an existing session to another location.
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
void switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
clear a state handler table from a given channel
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
#define switch_channel_down_nosig(_channel)
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
void switch_ivr_park_session(switch_core_session_t *session)
Definition: switch_ivr.c:3411
switch_channel_state_t
Channel States (these are the defaults, CS_SOFT_EXECUTE, CS_EXCHANGE_MEDIA, and CS_CONSUME_MEDIA are ...
#define switch_channel_down(_channel)
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_ivr_multi_threaded_bridge(switch_core_session_t *session, switch_core_session_t *peer_session, switch_input_callback_function_t input_callback, void *session_data, void *peer_session_data)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_channel_set_variable(_channel, _var, _val)
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
#define SWITCH_UUID_BRIDGE
Definition: switch_types.h:227

Variable Documentation

static const switch_state_handler_table_t audio_bridge_peer_state_handlers
static
Initial value:
= {
NULL,
NULL,
NULL,
NULL,
}
static switch_status_t audio_bridge_on_consume_media(switch_core_session_t *session)
static switch_status_t audio_bridge_on_exchange_media(switch_core_session_t *session)
static switch_status_t audio_bridge_on_routing(switch_core_session_t *session)

Definition at line 35 of file switch_ivr_bridge.c.

const switch_state_handler_table_t signal_bridge_state_handlers
static
Initial value:
= {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
}
static switch_status_t signal_bridge_on_hibernate(switch_core_session_t *session)
static switch_status_t signal_bridge_on_hangup(switch_core_session_t *session)

Definition at line 1315 of file switch_ivr_bridge.c.

const switch_state_handler_table_t uuid_bridge_state_handlers
static
Initial value:
= {
NULL,
NULL,
NULL,
NULL,
NULL,
}
static switch_status_t uuid_bridge_on_soft_execute(switch_core_session_t *session)
static switch_status_t uuid_bridge_on_reset(switch_core_session_t *session)
static switch_status_t uuid_bridge_on_hibernate(switch_core_session_t *session)

Definition at line 933 of file switch_ivr_bridge.c.