Insane amounts of yucky satanic code to make transfer and that kind of thing work.
Transfers work better when both legs of the call live in thier own channel eg bridged calls A -> B where you want a to make B -> C when you route a call to an IVR or playback app you are not really bridging you have A all alone executing the script so it's hard to transfer that. I do have it aparently working but it's goofy and you are better off putting your IVR on it's own switch so they are all inbound calls then you have A -> B -> IVR now A can happily transfer B who can stay on line with IVR without stopping the execution. You can also accomplish this by calling in a loop back to the same box if you dont want to have 2 boxes. Also the beginning effort at bridging calls with no media is here set this magic variable in your dialplan to convince mod_sofia to pass A's sdp as it's own to B and return B's sdp back to A on 200 or 183 <action application="set" data="no_media=true"/> <action application="bridge" data="sofia/id@host.com"/> You will need a new sofia tarball for this version There is a bunch of other odds and ends added like a function or 2 etc Oh, And don't be suprised if it introduces all kinds of bugs! git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2992 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
d7959131a3
commit
0d23976f2a
|
@ -223,6 +223,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
|
|||
void *session_data,
|
||||
void *peer_session_data);
|
||||
|
||||
/*!
|
||||
\brief Bridge Signalling from one session to another
|
||||
\param session one session
|
||||
\param peer_session the other session
|
||||
\return SWITCH_STATUS_SUCCESS if all is well
|
||||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_signal_bridge(switch_core_session_t *session, switch_core_session_t *peer_session);
|
||||
|
||||
/*!
|
||||
\brief Transfer an existing session to another location
|
||||
|
|
|
@ -72,6 +72,11 @@ SWITCH_BEGIN_EXTERN_C
|
|||
#define SWITCH_HTDOCS_DIR SWITCH_PREFIX_DIR SWITCH_PATH_SEPARATOR "htdocs"
|
||||
#endif
|
||||
|
||||
#define SWITCH_R_SDP_VARIABLE "_switch_r_sdp_"
|
||||
#define SWITCH_L_SDP_VARIABLE "_switch_l_sdp_"
|
||||
#define SWITCH_BRIDGE_VARIABLE "BRIDGETO"
|
||||
#define SWITCH_SIGNAL_BRIDGE_VARIABLE "SIGNAL_BRIDGETO"
|
||||
|
||||
#define SWITCH_BITS_PER_BYTE 8
|
||||
typedef uint8_t switch_byte_t;
|
||||
|
||||
|
@ -232,7 +237,8 @@ typedef enum {
|
|||
SWITCH_MESSAGE_TRANSMIT_TEXT - A text message
|
||||
SWITCH_MESSAGE_INDICATE_PROGRESS - indicate progress
|
||||
SWITCH_MESSAGE_INDICATE_BRIDGE - indicate a bridge starting
|
||||
SWITCH_MESSAGE_INDICATE_UNBRIDGE - indicate a bridge ending
|
||||
SWITCH_MESSAGE_INDICATE_UNBRIDGE - indicate a bridge ending
|
||||
SWITCH_MESSAGE_INDICATE_TRANSFER - indicate a transfer is taking place
|
||||
</pre>
|
||||
*/
|
||||
typedef enum {
|
||||
|
@ -240,7 +246,8 @@ typedef enum {
|
|||
SWITCH_MESSAGE_TRANSMIT_TEXT,
|
||||
SWITCH_MESSAGE_INDICATE_PROGRESS,
|
||||
SWITCH_MESSAGE_INDICATE_BRIDGE,
|
||||
SWITCH_MESSAGE_INDICATE_UNBRIDGE
|
||||
SWITCH_MESSAGE_INDICATE_UNBRIDGE,
|
||||
SWITCH_MESSAGE_INDICATE_TRANSFER
|
||||
} switch_core_session_message_types_t;
|
||||
|
||||
|
||||
|
@ -392,6 +399,7 @@ CF_SERVICE = (1 << 9) - Channel has a service thread
|
|||
CF_TAGGED = (1 << 10) - Channel is tagged
|
||||
CF_WINNER = (1 << 11) - Channel is the winner
|
||||
CF_CONTROLLED = (1 << 12) - Channel is under control
|
||||
CF_NOMEDIA = (1 << 13) - Channel has no media
|
||||
</pre>
|
||||
*/
|
||||
|
||||
|
@ -408,7 +416,8 @@ typedef enum {
|
|||
CF_SERVICE = (1 << 9),
|
||||
CF_TAGGED = (1 << 10),
|
||||
CF_WINNER = (1 << 11),
|
||||
CF_CONTROLLED = (1 << 12)
|
||||
CF_CONTROLLED = (1 << 12),
|
||||
CF_NOMEDIA = (1 << 13)
|
||||
} switch_channel_flag_t;
|
||||
|
||||
|
||||
|
|
|
@ -192,6 +192,16 @@ if (vname) {free(vname); vname = NULL;}vname = strdup(string);}
|
|||
*/
|
||||
SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, int arraylen);
|
||||
|
||||
/*!
|
||||
\brief Escape a string by prefixing a list of characters with an escape character
|
||||
\param pool a memory pool to use
|
||||
\param in the string
|
||||
\param delim the list of characters to escape
|
||||
\param esc the escape character
|
||||
\return the escaped string
|
||||
*/
|
||||
SWITCH_DECLARE(char *) switch_escape_char(switch_memory_pool_t *pool, char *in, char *delim, char esc);
|
||||
|
||||
/*!
|
||||
\brief Create a set of file descriptors to poll
|
||||
\param poll the polfd to create
|
||||
|
|
|
@ -51,23 +51,32 @@ static void audio_bridge_function(switch_core_session_t *session, char *data)
|
|||
timelimit = atoi(var);
|
||||
}
|
||||
|
||||
if ((var = switch_channel_get_variable(caller_channel, "no_media"))) {
|
||||
switch_channel_set_flag(caller_channel, CF_NOMEDIA);
|
||||
}
|
||||
|
||||
if (switch_ivr_originate(session, &peer_session, &cause, data, timelimit, NULL, NULL, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Create Outgoing Channel!\n");
|
||||
/* Hangup the channel with the cause code from the failed originate.*/
|
||||
switch_channel_hangup(caller_channel, cause);
|
||||
return;
|
||||
} else {
|
||||
switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL);
|
||||
if (switch_channel_test_flag(caller_channel, CF_NOMEDIA)) {
|
||||
switch_ivr_signal_bridge(session, peer_session);
|
||||
} else {
|
||||
switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const switch_application_interface_t bridge_application_interface = {
|
||||
/*.interface_name */ "bridge",
|
||||
/*.application_function */ audio_bridge_function
|
||||
/*.application_function */ audio_bridge_function,
|
||||
/* long_desc */ "Bridge the audio between two sessions",
|
||||
/* short_desc */ "Bridge Audio",
|
||||
/* syntax */ "<channel_url>",
|
||||
};
|
||||
|
||||
|
||||
static const switch_loadable_module_interface_t mod_bridgecall_module_interface = {
|
||||
/*.module_name = */ modname,
|
||||
/*.endpoint_interface = */ NULL,
|
||||
|
|
|
@ -62,6 +62,7 @@ typedef struct private_object private_object_t;
|
|||
#define MULTICAST_EVENT "multicast::event"
|
||||
#define SOFIA_REPLACES_HEADER "_sofia_replaces_"
|
||||
|
||||
|
||||
#include <sofia-sip/nua.h>
|
||||
#include <sofia-sip/sip_status.h>
|
||||
#include <sofia-sip/sdp.h>
|
||||
|
@ -131,7 +132,10 @@ typedef enum {
|
|||
TFLAG_TIMER = (1 << 14),
|
||||
TFLAG_READY = (1 << 15),
|
||||
TFLAG_REINVITE = (1 << 16),
|
||||
TFLAG_REFER = (1 << 17)
|
||||
TFLAG_REFER = (1 << 17),
|
||||
TFLAG_NOHUP = (1 << 18),
|
||||
TFLAG_XFER = (1 << 19),
|
||||
TFLAG_NOMEDIA = (1 << 20)
|
||||
} TFLAGS;
|
||||
|
||||
static struct {
|
||||
|
@ -250,11 +254,14 @@ struct private_object {
|
|||
char *local_sdp_str;
|
||||
char *dest;
|
||||
char *key;
|
||||
char *xferto;
|
||||
char *kick;
|
||||
unsigned long rm_rate;
|
||||
switch_payload_t pt;
|
||||
switch_mutex_t *flag_mutex;
|
||||
switch_payload_t te;
|
||||
nua_handle_t *nh;
|
||||
nua_handle_t *nh2;
|
||||
su_home_t *home;
|
||||
sip_contact_t *contact;
|
||||
};
|
||||
|
@ -594,8 +601,10 @@ static void set_local_sdp(private_object_t *tech_pvt)
|
|||
char buf[1024];
|
||||
switch_time_t now = switch_time_now();
|
||||
|
||||
assert(tech_pvt != NULL);
|
||||
|
||||
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf),
|
||||
"v=0\n"
|
||||
"o=FreeSWITCH %d%"APR_TIME_T_FMT" %d%"APR_TIME_T_FMT" IN IP4 %s\n"
|
||||
|
@ -653,6 +662,11 @@ static void set_local_sdp(private_object_t *tech_pvt)
|
|||
|
||||
static void tech_set_codecs(private_object_t *tech_pvt)
|
||||
{
|
||||
|
||||
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tech_pvt->num_codecs) {
|
||||
return;
|
||||
}
|
||||
|
@ -734,11 +748,11 @@ static switch_status_t tech_choose_port(private_object_t *tech_pvt)
|
|||
char *ip = tech_pvt->profile->rtpip;
|
||||
switch_port_t sdp_port;
|
||||
char *err;
|
||||
|
||||
if (tech_pvt->adv_sdp_audio_port) {
|
||||
|
||||
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA) || tech_pvt->adv_sdp_audio_port) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
tech_pvt->local_sdp_audio_ip = ip;
|
||||
tech_pvt->local_sdp_audio_port = switch_rtp_request_port();
|
||||
sdp_port = tech_pvt->local_sdp_audio_port;
|
||||
|
@ -787,6 +801,8 @@ static void do_invite(switch_core_session_t *session)
|
|||
|
||||
caller_profile = switch_channel_get_caller_profile(channel);
|
||||
|
||||
|
||||
|
||||
if ((tech_pvt->from_str = switch_core_db_mprintf("\"%s\" <sip:%s@%s>",
|
||||
(char *) caller_profile->caller_id_name,
|
||||
(char *) caller_profile->caller_id_number,
|
||||
|
@ -794,21 +810,75 @@ static void do_invite(switch_core_session_t *session)
|
|||
))) {
|
||||
|
||||
char *rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER);
|
||||
|
||||
|
||||
tech_choose_port(tech_pvt);
|
||||
set_local_sdp(tech_pvt);
|
||||
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_READY);
|
||||
|
||||
tech_pvt->nh = nua_handle(tech_pvt->profile->nua, NULL,
|
||||
if (!tech_pvt->nh) {
|
||||
tech_pvt->nh = nua_handle(tech_pvt->profile->nua, NULL,
|
||||
SIPTAG_TO_STR(tech_pvt->dest),
|
||||
SIPTAG_FROM_STR(tech_pvt->from_str),
|
||||
SIPTAG_CONTACT_STR(tech_pvt->profile->url),
|
||||
TAG_END());
|
||||
|
||||
tech_pvt->sofia_private.session = session;
|
||||
nua_handle_bind(tech_pvt->nh, &tech_pvt->sofia_private);
|
||||
|
||||
}
|
||||
|
||||
nua_invite(tech_pvt->nh,
|
||||
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
|
||||
SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE),
|
||||
SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL),
|
||||
TAG_IF(rep, SIPTAG_REPLACES_STR(rep)),
|
||||
TAG_END());
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void do_xfer_invite(switch_core_session_t *session)
|
||||
{
|
||||
private_object_t *tech_pvt;
|
||||
switch_channel_t *channel = NULL;
|
||||
switch_caller_profile_t *caller_profile;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
|
||||
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
|
||||
assert(tech_pvt != NULL);
|
||||
|
||||
caller_profile = switch_channel_get_caller_profile(channel);
|
||||
|
||||
|
||||
|
||||
if ((tech_pvt->from_str = switch_core_db_mprintf("\"%s\" <sip:%s@%s>",
|
||||
(char *) caller_profile->caller_id_name,
|
||||
(char *) caller_profile->caller_id_number,
|
||||
tech_pvt->profile->sipip
|
||||
))) {
|
||||
|
||||
char *rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER);
|
||||
|
||||
|
||||
tech_pvt->nh2 = nua_handle(tech_pvt->profile->nua, NULL,
|
||||
SIPTAG_TO_STR(tech_pvt->dest),
|
||||
SIPTAG_FROM_STR(tech_pvt->from_str),
|
||||
SIPTAG_CONTACT_STR(tech_pvt->profile->url),
|
||||
TAG_END());
|
||||
|
||||
|
||||
tech_pvt->sofia_private.session = session;
|
||||
nua_handle_bind(tech_pvt->nh, &tech_pvt->sofia_private);
|
||||
|
||||
nua_invite(tech_pvt->nh,
|
||||
nua_handle_bind(tech_pvt->nh2, &tech_pvt->sofia_private);
|
||||
|
||||
|
||||
|
||||
nua_invite(tech_pvt->nh2,
|
||||
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
|
||||
SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE),
|
||||
SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL),
|
||||
|
@ -829,6 +899,7 @@ static switch_status_t sofia_on_init(switch_core_session_t *session)
|
|||
{
|
||||
private_object_t *tech_pvt;
|
||||
switch_channel_t *channel = NULL;
|
||||
char *sdp;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
|
@ -841,6 +912,16 @@ static switch_status_t sofia_on_init(switch_core_session_t *session)
|
|||
switch_channel_set_variable(channel, "endpoint_disposition", "INIT");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SOFIA INIT\n");
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_NOMEDIA)) {
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_NOMEDIA);
|
||||
}
|
||||
|
||||
if ((sdp = switch_channel_get_variable(channel, SWITCH_L_SDP_VARIABLE))) {
|
||||
tech_pvt->local_sdp_str = switch_core_session_strdup(session, sdp);
|
||||
switch_set_flag(tech_pvt, TFLAG_NOMEDIA);
|
||||
switch_channel_set_flag(channel, CF_NOMEDIA);
|
||||
}
|
||||
|
||||
if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
|
||||
do_invite(session);
|
||||
}
|
||||
|
@ -937,6 +1018,7 @@ static int hangup_cause_to_sip(switch_call_cause_t cause) {
|
|||
|
||||
static switch_status_t sofia_on_hangup(switch_core_session_t *session)
|
||||
{
|
||||
switch_core_session_t *asession;
|
||||
private_object_t *tech_pvt;
|
||||
switch_channel_t *channel = NULL;
|
||||
switch_call_cause_t cause;
|
||||
|
@ -958,6 +1040,13 @@ static switch_status_t sofia_on_hangup(switch_core_session_t *session)
|
|||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel %s hanging up, cause: %s\n",
|
||||
switch_channel_get_name(channel), switch_channel_cause2str(cause), sip_cause);
|
||||
|
||||
|
||||
if (tech_pvt->kick && (asession = switch_core_session_locate(tech_pvt->kick))) {
|
||||
switch_channel_t *a_channel = switch_core_session_get_channel(asession);
|
||||
switch_channel_hangup(a_channel, switch_channel_get_cause(channel));
|
||||
switch_core_session_rwunlock(asession);
|
||||
}
|
||||
|
||||
if (tech_pvt->nh) {
|
||||
if (!switch_test_flag(tech_pvt, TFLAG_BYE)) {
|
||||
if (switch_test_flag(tech_pvt, TFLAG_ANS)) {
|
||||
|
@ -1088,6 +1177,9 @@ static switch_status_t activate_rtp(private_object_t *tech_pvt)
|
|||
channel = switch_core_session_get_channel(tech_pvt->session);
|
||||
assert(channel != NULL);
|
||||
|
||||
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (switch_rtp_ready(tech_pvt->rtp_session) && !switch_test_flag(tech_pvt, TFLAG_REINVITE)) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
@ -1168,7 +1260,8 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
|
|||
{
|
||||
private_object_t *tech_pvt;
|
||||
switch_channel_t *channel = NULL;
|
||||
|
||||
char *sdp;
|
||||
|
||||
assert(session != NULL);
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
|
@ -1177,13 +1270,25 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
|
|||
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
|
||||
assert(tech_pvt != NULL);
|
||||
|
||||
if ((sdp = switch_channel_get_variable(channel, SWITCH_L_SDP_VARIABLE))) {
|
||||
tech_pvt->local_sdp_str = switch_core_session_strdup(session, sdp);
|
||||
switch_set_flag(tech_pvt, TFLAG_NOMEDIA);
|
||||
switch_channel_set_flag(channel, CF_NOMEDIA);
|
||||
}
|
||||
|
||||
|
||||
if (!switch_test_flag(tech_pvt, TFLAG_ANS) && !switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_ANS);
|
||||
|
||||
|
||||
tech_choose_port(tech_pvt);
|
||||
set_local_sdp(tech_pvt);
|
||||
activate_rtp(tech_pvt);
|
||||
|
||||
if (tech_pvt->nh) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Local SDP:\n%s\n", tech_pvt->local_sdp_str);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Local SDP %s:\n%s\n",
|
||||
switch_channel_get_name(channel),
|
||||
tech_pvt->local_sdp_str);
|
||||
nua_respond(tech_pvt->nh, SIP_200_OK,
|
||||
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
|
||||
SOATAG_AUDIO_AUX("cn telephone-event"),
|
||||
|
@ -1203,10 +1308,6 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
|
|||
switch_channel_t *channel = NULL;
|
||||
int payload = 0;
|
||||
|
||||
//switch_time_t now, started = switch_time_now(), last_act = switch_time_now();
|
||||
//unsigned int elapsed;
|
||||
//uint32_t hard_timeout = 60000 * 3;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
|
||||
|
@ -1246,7 +1347,6 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
|
|||
|
||||
|
||||
while (!switch_test_flag(tech_pvt, TFLAG_BYE) && switch_test_flag(tech_pvt, TFLAG_IO) && tech_pvt->read_frame.datalen == 0) {
|
||||
//now = switch_time_now();
|
||||
tech_pvt->read_frame.flags = SFF_NONE;
|
||||
|
||||
status = switch_rtp_zerocopy_read_frame(tech_pvt->rtp_session, &tech_pvt->read_frame);
|
||||
|
@ -1448,6 +1548,34 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
|||
|
||||
switch (msg->message_id) {
|
||||
case SWITCH_MESSAGE_INDICATE_BRIDGE:
|
||||
|
||||
if (switch_test_flag(tech_pvt, TFLAG_XFER)) {
|
||||
switch_clear_flag_locked(tech_pvt, TFLAG_XFER);
|
||||
if (msg->pointer_arg) {
|
||||
switch_core_session_t *asession, *bsession = msg->pointer_arg;
|
||||
|
||||
if ((asession = switch_core_session_locate(tech_pvt->xferto))) {
|
||||
private_object_t *a_tech_pvt = switch_core_session_get_private(asession);
|
||||
private_object_t *b_tech_pvt = switch_core_session_get_private(bsession);
|
||||
|
||||
switch_set_flag_locked(a_tech_pvt, TFLAG_REINVITE);
|
||||
a_tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(asession, b_tech_pvt->remote_sdp_audio_ip);
|
||||
a_tech_pvt->remote_sdp_audio_port = b_tech_pvt->remote_sdp_audio_port;
|
||||
a_tech_pvt->local_sdp_audio_ip = switch_core_session_strdup(asession, b_tech_pvt->local_sdp_audio_ip);
|
||||
a_tech_pvt->local_sdp_audio_port = b_tech_pvt->local_sdp_audio_port;
|
||||
activate_rtp(a_tech_pvt);
|
||||
|
||||
b_tech_pvt->kick = switch_core_session_strdup(bsession, tech_pvt->xferto);
|
||||
|
||||
|
||||
switch_core_session_rwunlock(asession);
|
||||
}
|
||||
|
||||
|
||||
msg->pointer_arg = NULL;
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
}
|
||||
if (tech_pvt->rtp_session && switch_test_flag(tech_pvt, TFLAG_TIMER)) {
|
||||
switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "De-activate timed RTP!\n");
|
||||
|
@ -1462,17 +1590,26 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
|||
case SWITCH_MESSAGE_INDICATE_PROGRESS: {
|
||||
struct private_object *tech_pvt;
|
||||
switch_channel_t *channel = NULL;
|
||||
|
||||
char *sdp;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
|
||||
tech_pvt = switch_core_session_get_private(session);
|
||||
assert(tech_pvt != NULL);
|
||||
|
||||
|
||||
if (!switch_test_flag(tech_pvt, TFLAG_EARLY_MEDIA)) {
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Asked to send early media by %s\n", msg->from);
|
||||
|
||||
|
||||
if ((sdp = switch_channel_get_variable(channel, SWITCH_L_SDP_VARIABLE))) {
|
||||
tech_pvt->local_sdp_str = switch_core_session_strdup(session, sdp);
|
||||
switch_set_flag(tech_pvt, TFLAG_NOMEDIA);
|
||||
switch_channel_set_flag(channel, CF_NOMEDIA);
|
||||
}
|
||||
|
||||
|
||||
/* Transmit 183 Progress with SDP */
|
||||
tech_choose_port(tech_pvt);
|
||||
set_local_sdp(tech_pvt);
|
||||
|
@ -1540,6 +1677,7 @@ static switch_status_t sofia_outgoing_channel(switch_core_session_t *session, sw
|
|||
switch_caller_profile_t *caller_profile = NULL;
|
||||
private_object_t *tech_pvt = NULL;
|
||||
switch_channel_t *channel;
|
||||
switch_channel_t *nchannel;
|
||||
char *host;
|
||||
|
||||
*new_session = NULL;
|
||||
|
@ -1586,19 +1724,24 @@ static switch_status_t sofia_outgoing_channel(switch_core_session_t *session, sw
|
|||
tech_pvt->dest = switch_core_session_alloc(nsession, strlen(dest) + 5);
|
||||
snprintf(tech_pvt->dest, strlen(dest) + 5, "sip:%s", dest);
|
||||
}
|
||||
|
||||
channel = switch_core_session_get_channel(nsession);
|
||||
attach_private(nsession, profile, tech_pvt, dest);
|
||||
attach_private(nsession, profile, tech_pvt, dest);
|
||||
channel = switch_core_session_get_channel(session);
|
||||
nchannel = switch_core_session_get_channel(nsession);
|
||||
caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
|
||||
switch_channel_set_caller_profile(channel, caller_profile);
|
||||
switch_channel_set_flag(channel, CF_OUTBOUND);
|
||||
switch_channel_set_caller_profile(nchannel, caller_profile);
|
||||
switch_channel_set_flag(nchannel, CF_OUTBOUND);
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "OUTBOUND");
|
||||
switch_channel_set_state(nchannel, CS_INIT);
|
||||
switch_channel_set_variable(nchannel, "endpoint_disposition", "OUTBOUND");
|
||||
*new_session = nsession;
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
if (session) {
|
||||
char *val;
|
||||
switch_ivr_transfer_variable(session, nsession, SOFIA_REPLACES_HEADER);
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_NOMEDIA) && (val = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE))) {
|
||||
switch_channel_set_variable(nchannel, SWITCH_L_SDP_VARIABLE, val);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -1723,7 +1866,6 @@ static void sip_i_state(int status,
|
|||
|
||||
{
|
||||
char const *l_sdp = NULL, *r_sdp = NULL;
|
||||
//int audio = nua_active_inactive, video = nua_active_inactive, chat = nua_active_inactive;
|
||||
int offer_recv = 0, answer_recv = 0, offer_sent = 0, answer_sent = 0;
|
||||
int ss_state = nua_callstate_init;
|
||||
switch_channel_t *channel = NULL;
|
||||
|
@ -1758,6 +1900,7 @@ static void sip_i_state(int status,
|
|||
if (r_sdp) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Remote SDP:\n%s\n", r_sdp);
|
||||
tech_pvt->remote_sdp_str = switch_core_session_strdup(session, (char *)r_sdp);
|
||||
switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, (char *) r_sdp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1772,34 +1915,38 @@ static void sip_i_state(int status,
|
|||
case nua_callstate_proceeding:
|
||||
if (channel) {
|
||||
if (r_sdp) {
|
||||
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
|
||||
sdp_session_t *sdp;
|
||||
uint8_t match = 0;
|
||||
|
||||
if (tech_pvt->num_codecs) {
|
||||
if ((sdp = sdp_session(parser))) {
|
||||
match = negotiate_sdp(session, sdp);
|
||||
}
|
||||
}
|
||||
|
||||
if (parser) {
|
||||
sdp_parser_free(parser);
|
||||
}
|
||||
|
||||
|
||||
if (match) {
|
||||
tech_choose_port(tech_pvt);
|
||||
activate_rtp(tech_pvt);
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "EARLY MEDIA");
|
||||
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
|
||||
switch_channel_pre_answer(channel);
|
||||
return;
|
||||
} else {
|
||||
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
|
||||
sdp_session_t *sdp;
|
||||
uint8_t match = 0;
|
||||
|
||||
if (tech_pvt->num_codecs) {
|
||||
if ((sdp = sdp_session(parser))) {
|
||||
match = negotiate_sdp(session, sdp);
|
||||
}
|
||||
}
|
||||
|
||||
if (parser) {
|
||||
sdp_parser_free(parser);
|
||||
}
|
||||
|
||||
|
||||
if (match) {
|
||||
tech_choose_port(tech_pvt);
|
||||
activate_rtp(tech_pvt);
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "EARLY MEDIA");
|
||||
switch_channel_pre_answer(channel);
|
||||
return;
|
||||
}
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "NO CODECS");
|
||||
nua_respond(nh, SIP_488_NOT_ACCEPTABLE,
|
||||
TAG_END());
|
||||
}
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "NO CODECS");
|
||||
nua_respond(nh, SIP_488_NOT_ACCEPTABLE,
|
||||
TAG_END());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case nua_callstate_completing:
|
||||
nua_ack(nh, TAG_END());
|
||||
|
@ -1807,60 +1954,69 @@ static void sip_i_state(int status,
|
|||
case nua_callstate_received:
|
||||
if (channel) {
|
||||
if (r_sdp) {
|
||||
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
|
||||
sdp_session_t *sdp;
|
||||
uint8_t match = 0;
|
||||
|
||||
if (tech_pvt->num_codecs) {
|
||||
if ((sdp = sdp_session(parser))) {
|
||||
match = negotiate_sdp(session, sdp);
|
||||
}
|
||||
}
|
||||
|
||||
if (parser) {
|
||||
sdp_parser_free(parser);
|
||||
}
|
||||
|
||||
if (match) {
|
||||
nua_handle_t *bnh;
|
||||
sip_replaces_t *replaces;
|
||||
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "RECEIVED");
|
||||
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "RECEIVED_NOMEDIA");
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_READY);
|
||||
switch_core_session_thread_launch(session);
|
||||
|
||||
if (replaces_str && (replaces = sip_replaces_make(tech_pvt->home, replaces_str)) && (bnh = nua_handle_by_replaces(nua, replaces))) {
|
||||
sofia_private_t *b_private;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Processing Attended Transfer\n");
|
||||
while (switch_channel_get_state(channel) < CS_EXECUTE) {
|
||||
switch_yield(10000);
|
||||
return;
|
||||
} else {
|
||||
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
|
||||
sdp_session_t *sdp;
|
||||
uint8_t match = 0;
|
||||
|
||||
if (tech_pvt->num_codecs) {
|
||||
if ((sdp = sdp_session(parser))) {
|
||||
match = negotiate_sdp(session, sdp);
|
||||
}
|
||||
}
|
||||
|
||||
if ((b_private = nua_handle_fetch(bnh))) {
|
||||
char *br_b = switch_channel_get_variable(channel, "BRIDGETO");
|
||||
char *br_a = switch_core_session_get_uuid(b_private->session);
|
||||
if (parser) {
|
||||
sdp_parser_free(parser);
|
||||
}
|
||||
|
||||
if (br_b) {
|
||||
switch_ivr_uuid_bridge(br_a, br_b);
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "ATTENDED_TRANSFER");
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
|
||||
if (match) {
|
||||
nua_handle_t *bnh;
|
||||
sip_replaces_t *replaces;
|
||||
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "RECEIVED");
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_READY);
|
||||
switch_core_session_thread_launch(session);
|
||||
|
||||
if (replaces_str && (replaces = sip_replaces_make(tech_pvt->home, replaces_str)) && (bnh = nua_handle_by_replaces(nua, replaces))) {
|
||||
sofia_private_t *b_private;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Processing Replaces Attended Transfer\n");
|
||||
while (switch_channel_get_state(channel) < CS_EXECUTE) {
|
||||
switch_yield(10000);
|
||||
}
|
||||
|
||||
if ((b_private = nua_handle_fetch(bnh))) {
|
||||
char *br_b = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE);
|
||||
char *br_a = switch_core_session_get_uuid(b_private->session);
|
||||
|
||||
if (br_b) {
|
||||
switch_ivr_uuid_bridge(br_a, br_b);
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "ATTENDED_TRANSFER");
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
|
||||
} else {
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "ATTENDED_TRANSFER_ERROR");
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
}
|
||||
} else {
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "ATTENDED_TRANSFER_ERROR");
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
}
|
||||
} else {
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "ATTENDED_TRANSFER_ERROR");
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
nua_handle_unref(bnh);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "NO CODECS");
|
||||
nua_respond(nh, SIP_488_NOT_ACCEPTABLE,
|
||||
TAG_END());
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "NO CODECS");
|
||||
nua_respond(nh, SIP_488_NOT_ACCEPTABLE,
|
||||
TAG_END());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1869,76 +2025,103 @@ static void sip_i_state(int status,
|
|||
break;
|
||||
case nua_callstate_completed:
|
||||
if (tech_pvt && r_sdp) {
|
||||
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
|
||||
sdp_session_t *sdp;
|
||||
uint8_t match = 0;
|
||||
if (r_sdp) {
|
||||
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "What should i do?\n%s\n", r_sdp);
|
||||
return;
|
||||
} else {
|
||||
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
|
||||
sdp_session_t *sdp;
|
||||
uint8_t match = 0;
|
||||
|
||||
if (tech_pvt->num_codecs) {
|
||||
if ((sdp = sdp_session(parser))) {
|
||||
match = negotiate_sdp(session, sdp);
|
||||
if (tech_pvt->num_codecs) {
|
||||
if ((sdp = sdp_session(parser))) {
|
||||
match = negotiate_sdp(session, sdp);
|
||||
}
|
||||
}
|
||||
tech_choose_port(tech_pvt);
|
||||
set_local_sdp(tech_pvt);
|
||||
tech_set_codec(tech_pvt);
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_REINVITE);
|
||||
activate_rtp(tech_pvt);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Processing Reinvite\n");
|
||||
if (parser) {
|
||||
sdp_parser_free(parser);
|
||||
}
|
||||
}
|
||||
}
|
||||
tech_choose_port(tech_pvt);
|
||||
set_local_sdp(tech_pvt);
|
||||
tech_set_codec(tech_pvt);
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_REINVITE);
|
||||
activate_rtp(tech_pvt);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Processing Reinvite\n");
|
||||
if (parser) {
|
||||
sdp_parser_free(parser);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case nua_callstate_ready:
|
||||
if (nh == tech_pvt->nh2) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Cheater Reinvite!\n");
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_REINVITE);
|
||||
tech_pvt->nh = tech_pvt->nh2;
|
||||
tech_pvt->nh2 = NULL;
|
||||
tech_choose_port(tech_pvt);
|
||||
activate_rtp(tech_pvt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (channel) {
|
||||
if (r_sdp) {
|
||||
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
|
||||
sdp_session_t *sdp;
|
||||
uint8_t match = 0;
|
||||
|
||||
if (tech_pvt->num_codecs) {
|
||||
if ((sdp = sdp_session(parser))) {
|
||||
match = negotiate_sdp(session, sdp);
|
||||
}
|
||||
}
|
||||
|
||||
if (parser) {
|
||||
sdp_parser_free(parser);
|
||||
}
|
||||
|
||||
|
||||
if (match) {
|
||||
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_ANS);
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "ANSWER");
|
||||
tech_choose_port(tech_pvt);
|
||||
activate_rtp(tech_pvt);
|
||||
switch_channel_answer(channel);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
|
||||
sdp_session_t *sdp;
|
||||
uint8_t match = 0;
|
||||
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "NO CODECS");
|
||||
nua_respond(nh, SIP_488_NOT_ACCEPTABLE,
|
||||
TAG_END());
|
||||
if (tech_pvt->num_codecs) {
|
||||
if ((sdp = sdp_session(parser))) {
|
||||
match = negotiate_sdp(session, sdp);
|
||||
}
|
||||
}
|
||||
|
||||
if (parser) {
|
||||
sdp_parser_free(parser);
|
||||
}
|
||||
|
||||
|
||||
if (match) {
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_ANS);
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "ANSWER");
|
||||
tech_choose_port(tech_pvt);
|
||||
activate_rtp(tech_pvt);
|
||||
switch_channel_answer(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "NO CODECS");
|
||||
nua_respond(nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
|
||||
}
|
||||
} else if (switch_test_flag(tech_pvt, TFLAG_EARLY_MEDIA)) {
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_ANS);
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "ANSWER");
|
||||
switch_channel_answer(channel);
|
||||
return;
|
||||
} //else probably an ack
|
||||
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case nua_callstate_terminating:
|
||||
break;
|
||||
case nua_callstate_terminated:
|
||||
case nua_callstate_terminated:
|
||||
if (session) {
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_BYE);
|
||||
terminate_session(&session, sip_cause_to_freeswitch(status), __LINE__);
|
||||
if (switch_test_flag(tech_pvt, TFLAG_NOHUP)) {
|
||||
switch_clear_flag_locked(tech_pvt, TFLAG_NOHUP);
|
||||
nua_handle_destroy(tech_pvt->nh);
|
||||
tech_pvt->nh = NULL;
|
||||
} else {
|
||||
terminate_session(&session, sip_cause_to_freeswitch(status), __LINE__);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -2235,9 +2418,27 @@ static void sip_i_refer(nua_t *nua,
|
|||
|
||||
if (session) {
|
||||
private_object_t *tech_pvt = NULL;
|
||||
char *exten = NULL;
|
||||
char *etmp = NULL, *exten = NULL;
|
||||
switch_channel_t *channel_a = NULL, *channel_b = NULL;
|
||||
|
||||
tech_pvt = switch_core_session_get_private(session);
|
||||
channel_a = switch_core_session_get_channel(session);
|
||||
|
||||
|
||||
if (!sip->sip_cseq || !(etmp = switch_core_db_mprintf("refer;id=%u", sip->sip_cseq->cs_seq))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
if (switch_channel_test_flag(channel_a, CF_NOMEDIA)) {
|
||||
nua_notify(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
|
||||
SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden"),
|
||||
SIPTAG_EVENT_STR(etmp),
|
||||
TAG_END());
|
||||
goto done;
|
||||
}
|
||||
|
||||
from = sip->sip_from;
|
||||
to = sip->sip_to;
|
||||
|
||||
|
@ -2256,12 +2457,11 @@ static void sip_i_refer(nua_t *nua,
|
|||
char *rep;
|
||||
|
||||
if ((rep = strchr(refer_to->r_url->url_headers, '='))) {
|
||||
switch_channel_t *channel_a = NULL, *channel_b = NULL;
|
||||
char *br_a = NULL, *br_b = NULL;
|
||||
char *buf;
|
||||
rep++;
|
||||
|
||||
channel_a = switch_core_session_get_channel(session);
|
||||
|
||||
|
||||
if ((buf = switch_core_session_alloc(session, strlen(rep) + 1))) {
|
||||
rep = url_unescape(buf, (const char *) rep);
|
||||
|
@ -2272,45 +2472,86 @@ static void sip_i_refer(nua_t *nua,
|
|||
}
|
||||
if ((replaces = sip_replaces_make(tech_pvt->home, rep)) && (bnh = nua_handle_by_replaces(nua, replaces))) {
|
||||
sofia_private_t *b_private;
|
||||
|
||||
|
||||
switch_channel_set_variable(channel_a, SOFIA_REPLACES_HEADER, rep);
|
||||
if ((b_private = nua_handle_fetch(bnh))) {
|
||||
channel_b = switch_core_session_get_channel(b_private->session);
|
||||
|
||||
br_a = switch_channel_get_variable(channel_a, "BRIDGETO");
|
||||
br_b = switch_channel_get_variable(channel_b, "BRIDGETO");
|
||||
br_a = switch_channel_get_variable(channel_a, SWITCH_BRIDGE_VARIABLE);
|
||||
br_b = switch_channel_get_variable(channel_b, SWITCH_BRIDGE_VARIABLE);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Attended Transfer [%s][%s]\n", br_a, br_b);
|
||||
|
||||
if (br_a && br_b) {
|
||||
switch_ivr_uuid_bridge(br_a, br_b);
|
||||
switch_channel_set_variable(channel_b, "endpoint_disposition", "ATTENDED_TRANSFER");
|
||||
switch_channel_hangup(channel_b, SWITCH_CAUSE_ATTENDED_TRANSFER);
|
||||
switch_channel_set_variable(channel_a, "endpoint_disposition", "ATTENDED_TRANSFER");
|
||||
switch_channel_hangup(channel_a, SWITCH_CAUSE_ATTENDED_TRANSFER);
|
||||
|
||||
nua_notify(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
|
||||
SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"),
|
||||
SIPTAG_EVENT_STR(etmp),
|
||||
TAG_END());
|
||||
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Transfer! [%s][%s]\n", br_a, br_b);
|
||||
switch_channel_set_variable(channel_b, "endpoint_disposition", "ATTENDED_TRANSFER_ERROR");
|
||||
switch_channel_hangup(channel_b, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
switch_channel_set_variable(channel_a, "endpoint_disposition", "ATTENDED_TRANSFER_ERROR");
|
||||
switch_channel_hangup(channel_a, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
private_object_t *tech_pvt_b = (private_object_t *) switch_core_session_get_private(b_private->session);
|
||||
|
||||
if (!br_a && !br_b) {
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_NOHUP);
|
||||
switch_set_flag_locked(tech_pvt_b, TFLAG_XFER);
|
||||
tech_pvt_b->xferto = switch_core_session_strdup(b_private->session, switch_core_session_get_uuid(session));
|
||||
} else if (!br_a && br_b) {
|
||||
switch_core_session_t *bsession;
|
||||
|
||||
if ((bsession = switch_core_session_locate(br_b))) {
|
||||
private_object_t *b_tech_pvt = switch_core_session_get_private(bsession);
|
||||
switch_channel_t *b_channel = switch_core_session_get_channel(bsession);
|
||||
private_object_t *bp_tech_pvt = switch_core_session_get_private(b_private->session);
|
||||
|
||||
switch_core_session_get_uuid(b_private->session);
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_NOHUP);
|
||||
|
||||
switch_channel_clear_state_handler(b_channel, NULL);
|
||||
switch_channel_set_state_flag(b_channel, CF_TRANSFER);
|
||||
switch_channel_set_state(b_channel, CS_TRANSMIT);
|
||||
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_REINVITE);
|
||||
tech_pvt->local_sdp_audio_ip = switch_core_session_strdup(session, bp_tech_pvt->local_sdp_audio_ip);
|
||||
tech_pvt->local_sdp_audio_port = bp_tech_pvt->local_sdp_audio_port;
|
||||
|
||||
tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(session, b_tech_pvt->remote_sdp_audio_ip);
|
||||
tech_pvt->remote_sdp_audio_port = b_tech_pvt->remote_sdp_audio_port;
|
||||
activate_rtp(tech_pvt);
|
||||
|
||||
b_tech_pvt->kick = switch_core_session_strdup(bsession, switch_core_session_get_uuid(session));
|
||||
|
||||
|
||||
switch_core_session_rwunlock(bsession);
|
||||
}
|
||||
|
||||
switch_channel_hangup(channel_b, SWITCH_CAUSE_ATTENDED_TRANSFER);
|
||||
}
|
||||
|
||||
nua_notify(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
|
||||
SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"),
|
||||
SIPTAG_EVENT_STR(etmp),
|
||||
TAG_END());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
nua_handle_unref(bnh);
|
||||
} else { /* the other channel is on a different box, we have to go find them */
|
||||
if (exten && (br_a = switch_channel_get_variable(channel_a, "BRIDGETO"))) {
|
||||
switch_core_session_t *bsession;
|
||||
if (exten && (br_a = switch_channel_get_variable(channel_a, SWITCH_BRIDGE_VARIABLE))) {
|
||||
switch_core_session_t *asession;
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
|
||||
if ((bsession = switch_core_session_locate(br_a))) {
|
||||
if ((asession = switch_core_session_locate(br_a))) {
|
||||
switch_core_session_t *tsession;
|
||||
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
|
||||
uint32_t timeout = 60;
|
||||
char *tuuid_str;
|
||||
|
||||
channel = switch_core_session_get_channel(bsession);
|
||||
channel = switch_core_session_get_channel(asession);
|
||||
|
||||
exten = switch_core_db_mprintf("sofia/%s/%s@%s:%d",
|
||||
exten = switch_core_db_mprintf("sofia/%s/%s@%s:%s",
|
||||
profile->name,
|
||||
(char *) refer_to->r_url->url_user,
|
||||
(char *) refer_to->r_url->url_host,
|
||||
|
@ -2319,7 +2560,7 @@ static void sip_i_refer(nua_t *nua,
|
|||
|
||||
switch_channel_set_variable(channel, SOFIA_REPLACES_HEADER, rep);
|
||||
|
||||
if (switch_ivr_originate(bsession,
|
||||
if (switch_ivr_originate(asession,
|
||||
&tsession,
|
||||
&cause,
|
||||
exten,
|
||||
|
@ -2329,14 +2570,21 @@ static void sip_i_refer(nua_t *nua,
|
|||
NULL,
|
||||
NULL) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Create Outgoing Channel! [%s]\n", exten);
|
||||
nua_notify(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
|
||||
SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden"),
|
||||
SIPTAG_EVENT_STR(etmp),
|
||||
TAG_END());
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(bsession);
|
||||
switch_core_session_rwunlock(asession);
|
||||
tuuid_str = switch_core_session_get_uuid(tsession);
|
||||
switch_ivr_uuid_bridge(br_a, tuuid_str);
|
||||
switch_channel_set_variable(channel_a, "endpoint_disposition", "ATTENDED_TRANSFER");
|
||||
switch_channel_hangup(channel_a, SWITCH_CAUSE_ATTENDED_TRANSFER);
|
||||
nua_notify(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
|
||||
SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"),
|
||||
SIPTAG_EVENT_STR(etmp),
|
||||
TAG_END());
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
|
@ -2344,7 +2592,10 @@ static void sip_i_refer(nua_t *nua,
|
|||
} else { error:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Transfer! [%s]\n", br_a);
|
||||
switch_channel_set_variable(channel_a, "endpoint_disposition", "ATTENDED_TRANSFER_ERROR");
|
||||
switch_channel_hangup(channel_a, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
nua_notify(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
|
||||
SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden"),
|
||||
SIPTAG_EVENT_STR(etmp),
|
||||
TAG_END());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2362,26 +2613,50 @@ static void sip_i_refer(nua_t *nua,
|
|||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
char *br;
|
||||
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "BLIND_TRANSFER");
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_BLIND_TRANSFER);
|
||||
|
||||
if ((br = switch_channel_get_variable(channel, "BRIDGETO"))) {
|
||||
if ((br = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE))) {
|
||||
switch_core_session_t *bsession;
|
||||
|
||||
|
||||
if ((bsession = switch_core_session_locate(br))) {
|
||||
channel = switch_core_session_get_channel(bsession);
|
||||
switch_channel_set_variable(channel, "TRANSFER_FALLBACK", (char *) from->a_user);
|
||||
switch_ivr_session_transfer(bsession, exten, profile->dialplan, profile->context);
|
||||
switch_core_session_rwunlock(bsession);
|
||||
}
|
||||
}
|
||||
|
||||
switch_channel_set_variable(channel, "endpoint_disposition", "BLIND_TRANSFER");
|
||||
|
||||
nua_notify(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
|
||||
SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"),
|
||||
SIPTAG_EVENT_STR(etmp),
|
||||
TAG_END());
|
||||
} else {
|
||||
exten = switch_core_db_mprintf("sip:%s@%s:%s",
|
||||
(char *) refer_to->r_url->url_user,
|
||||
(char *) refer_to->r_url->url_host,
|
||||
refer_to->r_url->url_port);
|
||||
tech_pvt->dest = switch_core_session_strdup(session, exten);
|
||||
|
||||
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_NOHUP);
|
||||
|
||||
|
||||
nua_notify(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
|
||||
SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"),
|
||||
SIPTAG_EVENT_STR(etmp),
|
||||
TAG_END());
|
||||
|
||||
do_xfer_invite(session);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (strchr(exten, '@')) {
|
||||
if (exten && strchr(exten, '@')) {
|
||||
switch_core_db_free(exten);
|
||||
}
|
||||
if (etmp) {
|
||||
switch_core_db_free(etmp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2394,11 +2669,11 @@ static void sip_i_invite(nua_t *nua,
|
|||
tagi_t tags[])
|
||||
{
|
||||
switch_core_session_t *session = sofia_private ? sofia_private->session : NULL;
|
||||
//refer_handle_t *refer = sofia_private ? sofia_private->refer : NULL;
|
||||
char key[128] = "";
|
||||
|
||||
if (!session) {
|
||||
|
||||
if (!session) {
|
||||
|
||||
if ((profile->pflags & PFLAG_AUTH_CALLS)) {
|
||||
if (handle_register(nua, profile, nh, sip, REG_INVITE, key, sizeof(key))) {
|
||||
return;
|
||||
|
@ -2510,7 +2785,6 @@ static void sip_i_register(nua_t *nua,
|
|||
sip_t const *sip,
|
||||
tagi_t tags[])
|
||||
{
|
||||
//switch_core_session_t *session = sofia_private ? sofia_private->session : NULL;
|
||||
handle_register(nua, profile, nh, sip, REG_REGISTER, NULL, 0);
|
||||
}
|
||||
|
||||
|
@ -2547,15 +2821,11 @@ static void sip_r_register(int status,
|
|||
if ((tech_pvt = switch_core_session_get_private(session)) && switch_test_flag(tech_pvt, TFLAG_REFER)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "received reply from refer\n");
|
||||
|
||||
if (status == 200) {
|
||||
//crap
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!oreg) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No authentication available!\n");
|
||||
if (sofia_private->oreg) {
|
||||
nua_handle_destroy(nh);
|
||||
}
|
||||
|
@ -2906,9 +3176,7 @@ static void *SWITCH_THREAD_FUNC profile_thread_run(switch_thread_t *thread, void
|
|||
}
|
||||
|
||||
su_root_step(profile->s_root, 1000);
|
||||
//su_root_run(profile->s_root);
|
||||
}
|
||||
|
||||
|
||||
if (switch_event_create(&s_event, SWITCH_EVENT_UNPUBLISH) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._udp");
|
||||
|
|
|
@ -145,55 +145,55 @@ SWITCH_DECLARE(void) switch_caller_profile_event_set_data(switch_caller_profile_
|
|||
|
||||
if (caller_profile->username) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-Username", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->username);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->username);
|
||||
}
|
||||
if (caller_profile->dialplan) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-Dialplan", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->dialplan);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->dialplan);
|
||||
}
|
||||
if (caller_profile->caller_id_name) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-Caller-ID-Name", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->caller_id_name);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->caller_id_name);
|
||||
}
|
||||
if (caller_profile->caller_id_number) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-Caller-ID-Number", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->caller_id_number);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->caller_id_number);
|
||||
}
|
||||
if (caller_profile->network_addr) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-Network-Addr", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->network_addr);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->network_addr);
|
||||
}
|
||||
if (caller_profile->ani) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-ANI", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->ani);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->ani);
|
||||
}
|
||||
if (caller_profile->ani2) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-ANI2", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->ani2);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->ani2);
|
||||
}
|
||||
if (caller_profile->destination_number) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-Destination-Number", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->destination_number);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->destination_number);
|
||||
}
|
||||
if (caller_profile->uuid) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-Unique-ID", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->uuid);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->uuid);
|
||||
}
|
||||
if (caller_profile->source) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-Source", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->source);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->source);
|
||||
}
|
||||
if (caller_profile->context) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-Context", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->context);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->context);
|
||||
}
|
||||
if (caller_profile->rdnis) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-RDNIS", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->rdnis);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->rdnis);
|
||||
}
|
||||
if (caller_profile->chan_name) {
|
||||
snprintf(header_name, sizeof(header_name), "%s-Channel-Name", prefix);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, caller_profile->chan_name);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, "%s", caller_profile->chan_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_stream_write(switch_stream_handle
|
|||
ret = -1;
|
||||
} else {
|
||||
ret = 0;
|
||||
snprintf(end, remaining, data);
|
||||
snprintf(end, remaining, "%s", data);
|
||||
handle->data_len = strlen(buf);
|
||||
handle->end = (uint8_t *)(handle->data) + handle->data_len;
|
||||
}
|
||||
|
|
|
@ -2456,8 +2456,8 @@ static void switch_core_standard_on_execute(switch_core_session_t *session)
|
|||
|
||||
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(session->channel, event);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", extension->current_application->application_name);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", extension->current_application->application_data);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "%s", extension->current_application->application_name);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", extension->current_application->application_data);
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
application_interface->application_function(session, extension->current_application->application_data);
|
||||
|
|
153
src/switch_ivr.c
153
src/switch_ivr.c
|
@ -1372,7 +1372,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
|||
msg.from = __FILE__;
|
||||
switch_core_session_receive_message(session_a, &msg);
|
||||
|
||||
switch_channel_set_variable(chan_a, "BRIDGETO", NULL);
|
||||
switch_channel_set_variable(chan_a, SWITCH_BRIDGE_VARIABLE, NULL);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "BRIDGE THREAD DONE [%s]\n", switch_channel_get_name(chan_a));
|
||||
|
||||
switch_channel_clear_flag(chan_a, CF_BRIDGED);
|
||||
|
@ -1514,14 +1514,14 @@ static switch_status_t uuid_bridge_on_transmit(switch_core_session_t *session)
|
|||
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(channel, event);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "uuid_bridge");
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", switch_core_session_get_uuid(other_session));
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", switch_core_session_get_uuid(other_session));
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(other_channel, event);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "uuid_bridge");
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", switch_core_session_get_uuid(session));
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", switch_core_session_get_uuid(session));
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
|
@ -1912,7 +1912,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
|||
}
|
||||
endfor1:
|
||||
|
||||
if (session) {
|
||||
if (session && !switch_channel_test_flag(caller_channel, CF_NOMEDIA)) {
|
||||
switch_codec_t *read_codec = NULL;
|
||||
|
||||
switch_channel_pre_answer(caller_channel);
|
||||
|
@ -1946,7 +1946,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
|||
check_channel_status(peer_channels, peer_sessions, argc, &idx, file, key) && ((time(NULL) - start) < (time_t)timelimit_sec)) {
|
||||
|
||||
/* read from the channel while we wait if the audio is up on it */
|
||||
if (session && (switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA))) {
|
||||
if (session && !switch_channel_test_flag(caller_channel, CF_NOMEDIA) &&
|
||||
(switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA))) {
|
||||
switch_status_t status = switch_core_session_read_frame(session, &read_frame, 1000, 0);
|
||||
|
||||
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||
|
@ -1964,7 +1965,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
|||
|
||||
}
|
||||
|
||||
if (session) {
|
||||
if (session && !switch_channel_test_flag(caller_channel, CF_NOMEDIA)) {
|
||||
switch_core_session_reset(session);
|
||||
}
|
||||
|
||||
|
@ -1987,6 +1988,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
|||
}
|
||||
|
||||
if (caller_channel && switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
|
||||
char *val;
|
||||
|
||||
if (switch_channel_test_flag(peer_channel, CF_NOMEDIA) && (val = switch_channel_get_variable(peer_channel, SWITCH_R_SDP_VARIABLE))) {
|
||||
switch_channel_set_variable(caller_channel, SWITCH_L_SDP_VARIABLE, val);
|
||||
}
|
||||
switch_channel_answer(caller_channel);
|
||||
}
|
||||
|
||||
|
@ -2042,6 +2048,100 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
|||
}
|
||||
|
||||
|
||||
static switch_status_t signal_bridge_on_hangup(switch_core_session_t *session)
|
||||
{
|
||||
char *uuid;
|
||||
switch_channel_t *channel = NULL;
|
||||
switch_core_session_t *other_session;
|
||||
switch_event_t *event;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_ORIGINATOR)) {
|
||||
switch_channel_clear_flag(channel, CF_ORIGINATOR);
|
||||
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(channel, event);
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
|
||||
switch_channel_t *other_channel = NULL;
|
||||
|
||||
other_channel = switch_core_session_get_channel(other_session);
|
||||
assert(other_channel != NULL);
|
||||
|
||||
switch_channel_hangup(other_channel, switch_channel_get_cause(channel));
|
||||
switch_core_session_rwunlock(other_session);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const switch_state_handler_table_t signal_bridge_state_handlers = {
|
||||
/*.on_init */ NULL,
|
||||
/*.on_ring */ NULL,
|
||||
/*.on_execute */ NULL,
|
||||
/*.on_hangup */ signal_bridge_on_hangup,
|
||||
/*.on_loopback */ NULL,
|
||||
/*.on_transmit */ NULL,
|
||||
/*.on_hold */ NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_signal_bridge(switch_core_session_t *session, switch_core_session_t *peer_session)
|
||||
{
|
||||
switch_channel_t *caller_channel, *peer_channel;
|
||||
switch_event_t *event;
|
||||
|
||||
caller_channel = switch_core_session_get_channel(session);
|
||||
assert(caller_channel != NULL);
|
||||
|
||||
switch_channel_set_flag(caller_channel, CF_ORIGINATOR);
|
||||
|
||||
peer_channel = switch_core_session_get_channel(peer_session);
|
||||
assert(peer_channel != NULL);
|
||||
|
||||
switch_channel_set_variable(caller_channel, SWITCH_SIGNAL_BRIDGE_VARIABLE, switch_core_session_get_uuid(peer_session));
|
||||
switch_channel_set_variable(peer_channel, SWITCH_SIGNAL_BRIDGE_VARIABLE, switch_core_session_get_uuid(session));
|
||||
|
||||
switch_channel_clear_state_handler(caller_channel, NULL);
|
||||
switch_channel_clear_state_handler(peer_channel, NULL);
|
||||
|
||||
switch_channel_add_state_handler(caller_channel, &signal_bridge_state_handlers);
|
||||
switch_channel_add_state_handler(peer_channel, &signal_bridge_state_handlers);
|
||||
|
||||
|
||||
/* fire events that will change the data table from "show channels" */
|
||||
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(caller_channel, event);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "signal_bridge");
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", switch_core_session_get_uuid(peer_session));
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(peer_channel, event);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "signal_bridge");
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", switch_core_session_get_uuid(session));
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_BRIDGE) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(caller_channel, event);
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
switch_channel_set_state(caller_channel, CS_TRANSMIT);
|
||||
switch_channel_set_state(peer_channel, CS_TRANSMIT);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(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,
|
||||
|
@ -2102,18 +2202,32 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
|
|||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
|
||||
msg.from = __FILE__;
|
||||
msg.pointer_arg = session;
|
||||
|
||||
switch_core_session_receive_message(peer_session, &msg);
|
||||
msg.pointer_arg = peer_session;
|
||||
switch_core_session_receive_message(session, &msg);
|
||||
|
||||
if (switch_core_session_read_lock(peer_session) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_set_variable(caller_channel, "BRIDGETO", switch_core_session_get_uuid(peer_session));
|
||||
switch_channel_set_variable(peer_channel, "BRIDGETO", switch_core_session_get_uuid(session));
|
||||
switch_channel_set_variable(caller_channel, SWITCH_BRIDGE_VARIABLE, switch_core_session_get_uuid(peer_session));
|
||||
switch_channel_set_variable(peer_channel, SWITCH_BRIDGE_VARIABLE, switch_core_session_get_uuid(session));
|
||||
|
||||
msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
|
||||
msg.from = __FILE__;
|
||||
msg.pointer_arg = session;
|
||||
|
||||
switch_core_session_receive_message(peer_session, &msg);
|
||||
|
||||
if (!msg.pointer_arg) {
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
switch_core_session_rwunlock(peer_session);
|
||||
goto done;
|
||||
}
|
||||
|
||||
msg.pointer_arg = peer_session;
|
||||
switch_core_session_receive_message(session, &msg);
|
||||
|
||||
if (!msg.pointer_arg) {
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
switch_core_session_rwunlock(peer_session);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
switch_channel_set_private(peer_channel, "_bridge_", other_audio_thread);
|
||||
switch_channel_set_state(peer_channel, CS_LOOPBACK);
|
||||
audio_bridge_thread(NULL, (void *) this_audio_thread);
|
||||
|
@ -2164,6 +2278,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
|
|||
switch_channel_hangup(peer_channel, SWITCH_CAUSE_NO_ANSWER);
|
||||
}
|
||||
|
||||
done:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -2219,6 +2334,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_
|
|||
{
|
||||
switch_channel_t *channel;
|
||||
switch_caller_profile_t *profile, *new_profile;
|
||||
switch_core_session_message_t msg = {0};
|
||||
|
||||
assert(session != NULL);
|
||||
assert(extension != NULL);
|
||||
|
@ -2245,6 +2361,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_
|
|||
switch_channel_set_caller_profile(channel, new_profile);
|
||||
switch_channel_set_flag(channel, CF_TRANSFER);
|
||||
switch_channel_set_state(channel, CS_RING);
|
||||
|
||||
msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSFER;
|
||||
msg.from = __FILE__;
|
||||
switch_core_session_receive_message(session, &msg);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Transfer %s to %s[%s@%s]\n",
|
||||
switch_channel_get_name(channel), dialplan, extension, context);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
|
|
@ -329,6 +329,11 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_s
|
|||
return SWITCH_STATUS_SOCKERR;
|
||||
}
|
||||
|
||||
if (switch_socket_opt_set(rtp_session->sock, SWITCH_SO_REUSEADDR, 1) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "Socket Error!";
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (switch_socket_bind(rtp_session->sock, rtp_session->local_addr) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "Bind Error!";
|
||||
return SWITCH_STATUS_FALSE;
|
||||
|
|
|
@ -72,6 +72,45 @@ SWITCH_DECLARE(unsigned char) switch_char_to_rfc2833(char key)
|
|||
return '\0';
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(char *) switch_escape_char(switch_memory_pool_t *pool, char *in, char *delim, char esc)
|
||||
{
|
||||
char *data, *p, *d;
|
||||
int count = 1, i = 0;
|
||||
|
||||
p = in;
|
||||
while(*p) {
|
||||
d = delim;
|
||||
while (*d) {
|
||||
if (*p == *d) {
|
||||
count++;
|
||||
}
|
||||
d++;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
return in;
|
||||
}
|
||||
|
||||
data = switch_core_alloc(pool, strlen(in) + count);
|
||||
|
||||
p = in;
|
||||
while(*p) {
|
||||
d = delim;
|
||||
while (*d) {
|
||||
if (*p == *d) {
|
||||
data[i++] = esc;
|
||||
}
|
||||
d++;
|
||||
}
|
||||
data[i++] = *p;
|
||||
p++;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, int arraylen)
|
||||
{
|
||||
int argc;
|
||||
|
|
Loading…
Reference in New Issue