*/
SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_t *session, char *extension, char *dialplan, char *context);
-
/*!
\brief Bridge two existing sessions
\param originator_uuid the uuid of the originator
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(char *originator_uuid, char *originatee_uuid);
+/*!
+ \brief Signal a session to request direct media access to it's remote end
+ \param uuid the uuid of the session to request
+ \param flags flags to influence behaviour (SMF_REBRIDGE to rebridge the call in media mode)
+ \return SWITCH_STATUS_SUCCESS if all is well
+*/
+SWITCH_DECLARE(switch_status_t) switch_ivr_media(char *uuid, switch_media_flag_t flags);
+
+/*!
+ \brief Signal a session to request indirect media allowing it to exchange media directly with another device
+ \param uuid the uuid of the session to request
+ \param flags flags to influence behaviour (SMF_REBRIDGE to rebridge the call in no_media mode)
+ \return SWITCH_STATUS_SUCCESS if all is well
+*/
+SWITCH_DECLARE(switch_status_t) switch_ivr_nomedia(char *uuid, switch_media_flag_t flags);
+
+/*!
+ \brief Signal the session with a protocol specific hold message.
+ \param uuid the uuid of the session to hold
+ \return SWITCH_STATUS_SUCCESS if all is well
+*/
+SWITCH_DECLARE(switch_status_t) switch_ivr_hold_uuid(char *uuid);
+
+/*!
+ \brief Signal the session with a protocol specific unhold message.
+ \param uuid the uuid of the session to hold
+ \return SWITCH_STATUS_SUCCESS if all is well
+*/
+SWITCH_DECLARE(switch_status_t) switch_ivr_unhold_uuid(char *uuid);
+
+/*!
+ \brief Signal the session with a protocol specific hold message.
+ \param session the session to hold
+ \return SWITCH_STATUS_SUCCESS if all is well
+*/
+SWITCH_DECLARE(switch_status_t) switch_ivr_hold(switch_core_session_t *session);
+
+/*!
+ \brief Signal the session with a protocol specific unhold message.
+ \param uuid the uuid of the session to unhold
+ \return SWITCH_STATUS_SUCCESS if all is well
+*/
+SWITCH_DECLARE(switch_status_t) switch_ivr_unhold(switch_core_session_t *session);
+
+/*!
+ \brief Signal the session to broadcast audio
+ \param uuid the uuid of the session to broadcast on
+ \param path the path data of the broadcast "/path/to/file.wav [<timer name>]" or "speak:<engine>|<voice>|<Text to say>"
+ \param flags flags to send to the request (SMF_ECHO_BRIDGED to send the broadcast to both sides of the call)
+ \return SWITCH_STATUS_SUCCESS if all is well
+*/
+SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, switch_media_flag_t flags);
+
/*!
\brief Transfer variables from one session to another
\param sessa the original session
switch_state_handler_t on_transmit;
/*! executed when the state changes to hold*/
switch_state_handler_t on_hold;
+ /*! executed when the state changes to hibernate*/
+ switch_state_handler_t on_hibernate;
};
struct switch_stream_handle {
#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_B_SDP_VARIABLE "_switch_m_sdp_"
+#define SWITCH_BRIDGE_VARIABLE "_bridge_to_"
+#define SWITCH_SIGNAL_BRIDGE_VARIABLE "_signal_bridge_to_"
+#define SWITCH_ORIGINATOR_VARIABLE "_originator_"
+#define SWITCH_LOCAL_MEDIA_IP_VARIABLE "_local_media_ip_"
+#define SWITCH_LOCAL_MEDIA_PORT_VARIABLE "_local_media_port_"
+#define SWITCH_REMOTE_MEDIA_IP_VARIABLE "_remote_media_ip_"
+#define SWITCH_REMOTE_MEDIA_PORT_VARIABLE "_remote_media_port_"
+
#define SWITCH_BITS_PER_BYTE 8
typedef uint8_t switch_byte_t;
+typedef enum {
+ SMF_NONE = 0,
+ SMF_REBRIDGE = (1 << 0),
+ SMF_ECHO_BRIDGED = (1 << 1)
+} switch_media_flag_t;
+
typedef enum {
SWITCH_BITPACK_MODE_RFC3551,
SWITCH_BITPACK_MODE_AAL2
SWITCH_MESSAGE_INDICATE_BRIDGE - indicate a bridge starting
SWITCH_MESSAGE_INDICATE_UNBRIDGE - indicate a bridge ending
SWITCH_MESSAGE_INDICATE_TRANSFER - indicate a transfer is taking place
+ SWITCH_MESSAGE_INDICATE_MEDIA - indicate media is required
+ SWITCH_MESSAGE_INDICATE_NOMEDIA - indicate no-media is required
+ SWITCH_MESSAGE_INDICATE_HOLD - indicate hold
+ SWITCH_MESSAGE_INDICATE_UNHOLD - indicate unhold
</pre>
*/
typedef enum {
SWITCH_MESSAGE_INDICATE_BRIDGE,
SWITCH_MESSAGE_INDICATE_UNBRIDGE,
SWITCH_MESSAGE_INDICATE_TRANSFER,
- SWITCH_MESSAGE_INDICATE_RINGING
+ SWITCH_MESSAGE_INDICATE_RINGING,
+ SWITCH_MESSAGE_INDICATE_MEDIA,
+ SWITCH_MESSAGE_INDICATE_NOMEDIA,
+ SWITCH_MESSAGE_INDICATE_HOLD,
+ SWITCH_MESSAGE_INDICATE_UNHOLD,
} switch_core_session_message_types_t;
CS_EXECUTE - Channel is executing it's dialplan
CS_LOOPBACK - Channel is in loopback
CS_HOLD - Channel is on hold
+CS_HIBERNATE - Channel is in a sleep state
CS_HANGUP - Channel is flagged for hangup and ready to end
CS_DONE - Channel is ready to be destroyed and out of the state machine
</pre>
CS_EXECUTE,
CS_LOOPBACK,
CS_HOLD,
+ CS_HIBERNATE,
CS_HANGUP,
CS_DONE
} switch_channel_state_t;
CF_WINNER = (1 << 11) - Channel is the winner
CF_CONTROLLED = (1 << 12) - Channel is under control
CF_NOMEDIA = (1 << 13) - Channel has no media
+CF_SUSPEND = (1 << 14) - Suspend i/o
+CF_EVENT_PARSE = (1 << 15) - Suspend control events
</pre>
*/
CF_TAGGED = (1 << 10),
CF_WINNER = (1 << 11),
CF_CONTROLLED = (1 << 12),
- CF_NOMEDIA = (1 << 13)
+ CF_NOMEDIA = (1 << 13),
+ CF_SUSPEND = (1 << 14),
+ CF_EVENT_PARSE = (1 << 15)
} switch_channel_flag_t;
static switch_api_interface_t reload_api_interface;
static switch_api_interface_t kill_api_interface;
static switch_api_interface_t originate_api_interface;
+static switch_api_interface_t media_api_interface;
+static switch_api_interface_t hold_api_interface;
+static switch_api_interface_t broadcast_api_interface;
static switch_status_t status_function(char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream)
{
return SWITCH_STATUS_SUCCESS;
}
+static switch_status_t uuid_media_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
+{
+ char *argv[4] = {0};
+ int argc = 0;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ if (isession) {
+ return status;
+ }
+
+ argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+ if (argc < 1) {
+ stream->write_function(stream, "USAGE: %s\n", media_api_interface.syntax);
+ } else {
+ if (!strcmp(argv[0], "off")) {
+ status = switch_ivr_nomedia(argv[1], SMF_REBRIDGE);
+ } else {
+ status = switch_ivr_media(argv[0], SMF_REBRIDGE);
+ }
+ }
+
+ if (status == SWITCH_STATUS_SUCCESS) {
+ stream->write_function(stream, "+OK Success\n");
+ } else {
+ stream->write_function(stream, "-ERR Operation Failed\n");
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+static switch_status_t uuid_broadcast_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
+{
+ char *argv[4] = {0};
+ int argc = 0;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ if (isession) {
+ return status;
+ }
+
+ argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+ if (argc < 2) {
+ stream->write_function(stream, "USAGE: %s\n", broadcast_api_interface.syntax);
+ } else {
+ switch_media_flag_t flags = SMF_NONE;
+
+ if (argv[2] && !strcmp(argv[2], "both")) {
+ flags |= SMF_ECHO_BRIDGED;
+ }
+
+ status = switch_ivr_broadcast(argv[0], argv[1], flags);
+ stream->write_function(stream, "+OK Message Sent\n");
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t uuid_hold_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
+{
+ char *argv[4] = {0};
+ int argc = 0;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ if (isession) {
+ return status;
+ }
+
+ argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+ if (argc < 1) {
+ stream->write_function(stream, "USAGE: %s\n", hold_api_interface.syntax);
+ } else {
+ if (!strcmp(argv[0], "off")) {
+ status = switch_ivr_unhold_uuid(argv[1]);
+ } else {
+ status = switch_ivr_hold_uuid(argv[0]);
+ }
+ }
+
+ if (status == SWITCH_STATUS_SUCCESS) {
+ stream->write_function(stream, "+OK Success\n");
+ } else {
+ stream->write_function(stream, "-ERR Operation Failed\n");
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
static switch_status_t uuid_bridge_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
{
char *argv[4] = {0};
/*.next */ &help_api_interface
};
+static switch_api_interface_t media_api_interface = {
+ /*.interface_name */ "media",
+ /*.desc */ "media",
+ /*.function */ uuid_media_function,
+ /*.syntax */ "<uuid>",
+ /*.next */ &ctl_api_interface
+};
+
+static switch_api_interface_t hold_api_interface = {
+ /*.interface_name */ "hold",
+ /*.desc */ "hold",
+ /*.function */ uuid_hold_function,
+ /*.syntax */ "<uuid>",
+ /*.next */ &media_api_interface
+};
+
+static switch_api_interface_t broadcast_api_interface = {
+ /*.interface_name */ "broadcast",
+ /*.desc */ "broadcast",
+ /*.function */ uuid_broadcast_function,
+ /*.syntax */ "<uuid> <path> [both]",
+ /*.next */ &hold_api_interface
+};
+
static switch_api_interface_t uuid_bridge_api_interface = {
/*.interface_name */ "uuid_bridge",
/*.desc */ "uuid_bridge",
/*.function */ uuid_bridge_function,
/*.syntax */ "<uuid> <other_uuid>",
- /*.next */ &ctl_api_interface
+ /*.next */ &broadcast_api_interface
};
static switch_api_interface_t status_api_interface = {
timer_name = argv[3];
if (!(engine && voice && text)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Params!\n");
+ if (!engine) {
+ engine = "NULL";
+ }
+ if (!voice) {
+ voice = "NULL";
+ }
+ if (!text) {
+ text = "NULL";
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Params! [%s][%s][%s]\n", engine, voice, text);
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
OS_ARCH := $(subst /,_,$(shell uname -s | sed /\ /s//_/))
VERSION = sofia-sip-1.12
-TARBALL = sofia-sip-1.12.3.8.tar.gz
+TARBALL = sofia-sip-1.12.3.9.tar.gz
CFLAGS += -I. -I$(PREFIX)/include/$(VERSION)
LDFLAGS += -lsofia-sip-ua
LINKER=$(CC)
extern su_log_t tport_log[];
+static switch_frame_t silence_frame = {};
+static char silence_data[13] = "";
+
+
static char reg_sql[] =
"CREATE TABLE sip_registrations (\n"
" user VARCHAR(255),\n"
typedef enum {
TFLAG_IO = (1 << 0),
- TFLAG_INBOUND = (1 << 1),
+ TFLAG_USEME = (1 << 1),
TFLAG_OUTBOUND = (1 << 2),
TFLAG_READING = (1 << 3),
TFLAG_WRITING = (1 << 4),
switch_port_t remote_sdp_audio_port;
char *adv_sdp_audio_ip;
switch_port_t adv_sdp_audio_port;
+ char *proxy_sdp_audio_ip;
+ switch_port_t proxy_sdp_audio_port;
char *from_uri;
char *to_uri;
char *from_address;
static void deactivate_rtp(private_object_t *tech_pvt);
-static void set_local_sdp(private_object_t *tech_pvt);
+static void set_local_sdp(private_object_t *tech_pvt, char *ip, uint32_t port, char *sr, int force);
static void tech_set_codecs(private_object_t *tech_pvt);
}
-static void set_local_sdp(private_object_t *tech_pvt)
+static void set_local_sdp(private_object_t *tech_pvt, char *ip, uint32_t port, char *sr, int force)
{
char buf[1024];
switch_time_t now = switch_time_now();
- if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
+ if (!force && !ip && !sr && switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
return;
}
+ if (!ip) {
+ if (!(ip = tech_pvt->adv_sdp_audio_ip)) {
+ ip = tech_pvt->proxy_sdp_audio_ip;
+ }
+ }
+ if (!port) {
+ if (!(port = tech_pvt->adv_sdp_audio_port)) {
+ port = tech_pvt->proxy_sdp_audio_port;
+ }
+ }
+ if (!sr) {
+ sr = "sendrecv";
+ }
+
snprintf(buf, sizeof(buf),
"v=0\n"
"o=FreeSWITCH %d%"APR_TIME_T_FMT" %d%"APR_TIME_T_FMT" IN IP4 %s\n"
"s=FreeSWITCH\n"
"c=IN IP4 %s\n"
"t=0 0\n"
- "a=sendrecv\n"
+ "a=%s\n"
"m=audio %d RTP/AVP",
- tech_pvt->adv_sdp_audio_port,
+ port,
now,
- tech_pvt->adv_sdp_audio_port,
+ port,
now,
- tech_pvt->adv_sdp_audio_ip,
- tech_pvt->adv_sdp_audio_ip,
- tech_pvt->adv_sdp_audio_port
+ ip,
+ ip,
+ sr,
+ port
);
if (tech_pvt->rm_encoding) {
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", tech_pvt->te, tech_pvt->te);
}
-
-
-
tech_pvt->local_sdp_str = switch_core_session_strdup(tech_pvt->session, buf);
-
}
static void tech_set_codecs(private_object_t *tech_pvt)
}
}
+
static switch_status_t tech_choose_port(private_object_t *tech_pvt)
{
char *ip = tech_pvt->profile->rtpip;
+ switch_channel_t *channel;
switch_port_t sdp_port;
char *err;
+ char tmp[50];
+ channel = switch_core_session_get_channel(tech_pvt->session);
+
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA) || tech_pvt->adv_sdp_audio_port) {
return SWITCH_STATUS_SUCCESS;
}
tech_pvt->adv_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, ip);
tech_pvt->adv_sdp_audio_port = sdp_port;
+
+ snprintf(tmp, sizeof(tmp), "%d", sdp_port);
+ switch_channel_set_variable(channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip);
+ switch_channel_set_variable(channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, tmp);
+
+
return SWITCH_STATUS_SUCCESS;
}
switch_caller_profile_t *caller_profile;
char *cid_name, *cid_num;
char *e_dest = NULL;
+ char *holdstr = "";
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
}
tech_choose_port(tech_pvt);
- set_local_sdp(tech_pvt);
+ set_local_sdp(tech_pvt, NULL, 0, NULL, 0);
switch_set_flag_locked(tech_pvt, TFLAG_READY);
}
+ holdstr = switch_test_flag(tech_pvt, TFLAG_SIP_HOLD) ? "*" : "";
nua_invite(tech_pvt->nh,
TAG_IF(rpid, SIPTAG_HEADER_STR(rpid)),
TAG_IF(alert_info, SIPTAG_HEADER_STR(alert_info)),
+ SIPTAG_CONTACT_STR(tech_pvt->profile->url),
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)),
+ SOATAG_HOLD(holdstr),
TAG_END());
+
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
}
nua_invite(tech_pvt->nh2,
TAG_IF(rpid, SIPTAG_HEADER_STR(rpid)),
+ SIPTAG_CONTACT_STR(tech_pvt->profile->url),
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE),
SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL),
}
+static void tech_absorb_sdp(private_object_t *tech_pvt)
+{
+ switch_channel_t *channel;
+ char *sdp_str;
+
+ channel = switch_core_session_get_channel(tech_pvt->session);
+ assert(channel != NULL);
+
+ if ((sdp_str = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE))) {
+ sdp_parser_t *parser;
+ sdp_session_t *sdp;
+ sdp_media_t *m;
+
+ if ((parser = sdp_parse(tech_pvt->home, sdp_str, (int)strlen(sdp_str), 0))) {
+ if ((sdp = sdp_session(parser))) {
+ for (m = sdp->sdp_media; m ; m = m->m_next) {
+ tech_pvt->proxy_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, (char *)sdp->sdp_connection->c_address);
+ tech_pvt->proxy_sdp_audio_port = (switch_port_t)m->m_port;
+ break;
+ }
+ }
+ sdp_parser_free(parser);
+ }
+ tech_pvt->local_sdp_str = switch_core_session_strdup(tech_pvt->session, sdp_str);
+ }
+}
+
/*
State methods they get called when the state changes to the specific state
returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
{
private_object_t *tech_pvt;
switch_channel_t *channel = NULL;
- char *sdp;
-
+
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
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);
+ tech_absorb_sdp(tech_pvt);
}
if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending BYE\n");
nua_bye(tech_pvt->nh, TAG_END());
} else {
- if (switch_test_flag(tech_pvt, TFLAG_INBOUND)) {
+ if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Responding to INVITE with: %d\n", sip_cause);
nua_respond(tech_pvt->nh, sip_cause, NULL, TAG_END());
} else {
const char *err = NULL;
switch_rtp_flag_t flags;
switch_status_t status;
-
+ char tmp[50];
assert(tech_pvt != NULL);
channel = switch_core_session_get_channel(tech_pvt->session);
tech_pvt->agreed_pt,
tech_pvt->read_codec.implementation->microseconds_per_frame / 1000);
-
+ snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
+ switch_channel_set_variable(channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip);
+ switch_channel_set_variable(channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, tmp);
+
if (tech_pvt->rtp_session && switch_test_flag(tech_pvt, TFLAG_REINVITE)) {
switch_clear_flag_locked(tech_pvt, TFLAG_REINVITE);
{
private_object_t *tech_pvt;
switch_channel_t *channel = NULL;
- char *sdp;
assert(session != NULL);
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_channel_test_flag(channel, CF_NOMEDIA)) {
+ switch_set_flag_locked(tech_pvt, TFLAG_NOMEDIA);
+ tech_absorb_sdp(tech_pvt);
}
-
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);
+ set_local_sdp(tech_pvt, NULL, 0, NULL, 0);
activate_rtp(tech_pvt);
if (tech_pvt->nh) {
size_t bytes = 0, samples = 0, frames = 0, ms = 0;
switch_channel_t *channel = NULL;
int payload = 0;
-
+
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
return SWITCH_STATUS_FALSE;
}
+ while (!(tech_pvt->read_codec.implementation && switch_rtp_ready(tech_pvt->rtp_session))) {
+ if (switch_channel_ready(channel)) {
+ switch_yield(10000);
+ } else {
+ return SWITCH_STATUS_GENERR;
+ }
+ }
+
+
tech_pvt->read_frame.datalen = 0;
switch_set_flag_locked(tech_pvt, TFLAG_READING);
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
assert(tech_pvt != NULL);
+ while (!(tech_pvt->read_codec.implementation && switch_rtp_ready(tech_pvt->rtp_session))) {
+ if (switch_channel_ready(channel)) {
+ switch_yield(10000);
+ } else {
+ return SWITCH_STATUS_GENERR;
+ }
+ }
+
if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
return SWITCH_STATUS_FALSE;
}
switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_NOMEDIA: {
+ char *uuid;
+ switch_core_session_t *other_session;
+ switch_channel_t *other_channel;
+ char *ip = NULL, *port = NULL;
+
+ switch_set_flag_locked(tech_pvt, TFLAG_NOMEDIA);
+ tech_pvt->local_sdp_str = NULL;
+ if ((uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
+ other_channel = switch_core_session_get_channel(other_session);
+ ip = switch_channel_get_variable(other_channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE);
+ port = switch_channel_get_variable(other_channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE);
+ switch_core_session_rwunlock(other_session);
+ if (ip && port) {
+ set_local_sdp(tech_pvt, ip, atoi(port), NULL, 1);
+ }
+ }
+ if (!tech_pvt->local_sdp_str) {
+ tech_absorb_sdp(tech_pvt);
+ }
+
+ do_invite(session);
+ }
+ break;
+ case SWITCH_MESSAGE_INDICATE_MEDIA: {
+ switch_clear_flag_locked(tech_pvt, TFLAG_NOMEDIA);
+ tech_pvt->local_sdp_str = NULL;
+ if (!switch_rtp_ready(tech_pvt->rtp_session)) {
+ tech_set_codecs(tech_pvt);
+ tech_choose_port(tech_pvt);
+ }
+ set_local_sdp(tech_pvt, NULL, 0, NULL, 1);
+ do_invite(session);
+ }
+ break;
+
+ case SWITCH_MESSAGE_INDICATE_HOLD: {
+ switch_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+ do_invite(session);
+ }
+ break;
+
+ case SWITCH_MESSAGE_INDICATE_UNHOLD: {
+ switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+ do_invite(session);
+ }
+ break;
case SWITCH_MESSAGE_INDICATE_BRIDGE:
if (switch_test_flag(tech_pvt, TFLAG_XFER)) {
switch_core_session_rwunlock(asession);
}
-
+
msg->pointer_arg = NULL;
return SWITCH_STATUS_FALSE;
}
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)) {
+ if (!switch_test_flag(tech_pvt, TFLAG_EARLY_MEDIA) && !switch_test_flag(tech_pvt, TFLAG_ANS)) {
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);
+ if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
+ tech_absorb_sdp(tech_pvt);
}
-
/* Transmit 183 Progress with SDP */
tech_choose_port(tech_pvt);
- set_local_sdp(tech_pvt);
+ set_local_sdp(tech_pvt, NULL, 0, NULL, 0);
activate_rtp(tech_pvt);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "183 SDP:\n%s\n", tech_pvt->local_sdp_str);
- nua_respond(tech_pvt->nh, SIP_183_SESSION_PROGRESS,
- SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
- SOATAG_AUDIO_AUX("cn telephone-event"),
- TAG_END());
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Ring SDP:\n%s\n", tech_pvt->local_sdp_str);
+
+
+ if (msg->message_id == SWITCH_MESSAGE_INDICATE_RINGING) {
+ nua_respond(tech_pvt->nh,
+ SIP_180_RINGING,
+ SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
+ SOATAG_AUDIO_AUX("cn telephone-event"),
+ TAG_END());
+ } else {
+ nua_respond(tech_pvt->nh,
+ SIP_183_SESSION_PROGRESS,
+ SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
+ SOATAG_AUDIO_AUX("cn telephone-event"),
+ TAG_END());
+ }
}
}
break;
*new_session = nsession;
status = SWITCH_STATUS_SUCCESS;
if (session) {
- char *val;
- switch_channel_t *channel = switch_core_session_get_channel(session);
+ //char *val;
+ //switch_channel_t *channel = switch_core_session_get_channel(session);
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:
private_object_t *tech_pvt;
sdp_media_t *m;
sdp_attribute_t *a;
-
+ switch_channel_t *channel;
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
+
+ channel = switch_core_session_get_channel(session);
if ((tech_pvt->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) {
if (strstr(tech_pvt->origin, "CiscoSystemsSIP-GW-UserAgent")) {
} else {
match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1;
}
-
+
if (match && (map->rm_rate == imp->samples_per_second)) {
+ char tmp[50];
tech_pvt->rm_encoding = switch_core_session_strdup(session, (char *)map->rm_encoding);
tech_pvt->pt = (switch_payload_t)map->rm_pt;
tech_pvt->rm_rate = map->rm_rate;
tech_pvt->rm_fmtp = switch_core_session_strdup(session, (char *)map->rm_fmtp);
tech_pvt->remote_sdp_audio_port = (switch_port_t)m->m_port;
tech_pvt->agreed_pt = (switch_payload_t)map->rm_pt;
+ snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
+ switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
+ switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
break;
} else {
match = 0;
}
}
+static void pass_sdp(switch_channel_t *channel, char *sdp)
+{
+ char *val;
+ switch_core_session_t *other_session;
+ switch_channel_t *other_channel;
+
+ if ((val = switch_channel_get_variable(channel, SWITCH_ORIGINATOR_VARIABLE)) && (other_session = switch_core_session_locate(val))) {
+ other_channel = switch_core_session_get_channel(other_session);
+ assert(other_channel != NULL);
+ if (!switch_channel_get_variable(other_channel, SWITCH_B_SDP_VARIABLE)) {
+ switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, sdp);
+ }
+ if (
+ switch_channel_test_flag(other_channel, CF_OUTBOUND) &&
+ switch_channel_test_flag(other_channel, CF_NOMEDIA) &&
+ switch_channel_test_flag(channel, CF_OUTBOUND) &&
+ switch_channel_test_flag(channel, CF_NOMEDIA)) {
+ switch_ivr_nomedia(val, SMF_NONE);
+ }
+
+ switch_core_session_rwunlock(other_session);
+ }
+}
+
static void sip_i_state(int status,
char const *phrase,
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);
+ pass_sdp(channel, (char *) r_sdp);
}
}
+ if (status == 988) {
+ return;
+ }
switch ((enum nua_callstate)ss_state) {
case nua_callstate_init:
if (channel) {
if (status == 180) {
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
- if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
+ if ((uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
switch_core_session_message_t msg;
msg.message_id = SWITCH_MESSAGE_INDICATE_RINGING;
msg.from = __FILE__;
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
switch_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
switch_channel_set_flag(channel, CF_EARLY_MEDIA);
- if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
+ if ((uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
other_channel = switch_core_session_get_channel(other_session);
switch_channel_pre_answer(other_channel);
switch_core_session_rwunlock(other_session);
switch_channel_set_variable(channel, "endpoint_disposition", "RECEIVED");
switch_channel_set_state(channel, CS_INIT);
switch_set_flag_locked(tech_pvt, TFLAG_READY);
- //sofia_answer_channel(session);//XXX TMP
+
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))) {
}
if (match) {
tech_choose_port(tech_pvt);
- set_local_sdp(tech_pvt);
+ set_local_sdp(tech_pvt, NULL, 0, NULL, 0);
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 (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
switch_set_flag_locked(tech_pvt, TFLAG_ANS);
switch_channel_set_flag(channel, CF_ANSWERED);
- if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
+ if ((uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
other_channel = switch_core_session_get_channel(other_session);
switch_channel_answer(other_channel);
switch_core_session_rwunlock(other_session);
switch_safe_free(to_username);
}
- switch_set_flag_locked(tech_pvt, TFLAG_INBOUND);
tech_pvt->sofia_private.session = session;
nua_handle_bind(nh, &tech_pvt->sofia_private);
}
}
if (!oreg) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Register handle to associate!\n");
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Register handle to associate!\n");
return;
}
TAG_END()); /* Last tag should always finish the sequence */
nua_set_params(profile->nua,
- NUTAG_EARLY_MEDIA(1),
+ //NUTAG_EARLY_MEDIA(1),
NUTAG_AUTOANSWER(0),
NUTAG_AUTOALERT(0),
NUTAG_ALLOW("REGISTER"),
SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)
{
+ silence_frame.data = silence_data;
+ silence_frame.datalen = sizeof(silence_data);
+ silence_frame.buflen = sizeof(silence_data);
+ silence_frame.flags = SFF_CNG;
+
+
if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
return SWITCH_STATUS_TERM;
"CS_EXECUTE",
"CS_LOOPBACK",
"CS_HOLD",
+ "CS_HIBERNATE",
"CS_HANGUP",
"CS_DONE",
NULL
case CS_RING:
case CS_EXECUTE:
case CS_HOLD:
+ case CS_HIBERNATE:
ok++;
default:
break;
case CS_RING:
case CS_EXECUTE:
case CS_HOLD:
+ case CS_HIBERNATE:
ok++;
default:
break;
case CS_RING:
case CS_EXECUTE:
case CS_HOLD:
+ case CS_HIBERNATE:
ok++;
default:
break;
case CS_RING:
case CS_EXECUTE:
case CS_TRANSMIT:
+ case CS_HIBERNATE:
+ ok++;
+ default:
+ break;
+ }
+ break;
+ case CS_HIBERNATE:
+ switch (state) {
+ case CS_LOOPBACK:
+ case CS_RING:
+ case CS_EXECUTE:
+ case CS_TRANSMIT:
+ case CS_HOLD:
ok++;
default:
break;
case CS_EXECUTE:
case CS_TRANSMIT:
case CS_HOLD:
+ case CS_HIBERNATE:
ok++;
default:
break;
case CS_TRANSMIT:
case CS_RING:
case CS_HOLD:
+ case CS_HIBERNATE:
ok++;
default:
break;
switch_event_t *event;
switch_channel_t *peer_channel = switch_core_session_get_channel(*new_session);
+
if (session && channel) {
profile = switch_channel_get_caller_profile(channel);
}
}
if (channel && peer_channel) {
- char *export_vars;
+ char *export_vars, *val;
+
+ switch_channel_set_variable(peer_channel, SWITCH_ORIGINATOR_VARIABLE, switch_core_session_get_uuid(session));
+
/* A comma (,) separated list of variable names that should ne propagated from originator to originatee */
if ((export_vars = switch_channel_get_variable(channel, "export_vars"))) {
char *cptmp = switch_core_session_strdup(session, export_vars);
}
}
+ if ((val = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE))) {
+ switch_channel_set_variable(peer_channel, SWITCH_B_SDP_VARIABLE, val);
+ }
+
+ if (switch_channel_test_flag(channel, CF_NOMEDIA)) {
+ switch_channel_set_flag(peer_channel, CF_NOMEDIA);
+ }
+
if (profile) {
if ((cloned_profile = switch_caller_profile_clone(*new_session, profile)) != 0) {
switch_channel_set_originator_caller_profile(peer_channel, cloned_profile);
switch_status_t status = SWITCH_STATUS_FALSE;
assert(session != NULL);
-
+
if (!session->private_event_queue) {
switch_queue_create(&session->private_event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool);
}
{
switch_status_t status = SWITCH_STATUS_FALSE;
void *pop;
+ switch_channel_t *channel;
assert(session != NULL);
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ if (switch_channel_test_flag(channel, CF_EVENT_PARSE)) {
+ return status;
+ }
+
if (session->private_event_queue) {
if ((status = (switch_status_t) switch_queue_trypop(session->private_event_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
assert(session != NULL);
assert(frame != NULL);
- assert(frame->codec != NULL);
+
if (switch_channel_test_flag(session->channel, CF_HOLD)) {
return SWITCH_STATUS_SUCCESS;
return SWITCH_STATUS_SUCCESS;
}
+ assert(frame->codec != NULL);
if ((session->write_codec && frame->codec && session->write_codec->implementation != frame->codec->implementation)) {
need_codec = TRUE;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard HOLD\n");
}
+static void switch_core_standard_on_hibernate(switch_core_session_t *session)
+{
+ assert(session != NULL);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard HIBERNATE\n");
+}
+
SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session_t *session)
{
}
}
break;
+ case CS_HIBERNATE: /* wait in limbo */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State HIBERNATE\n", switch_channel_get_name(session->channel));
+ if (!driver_state_handler->on_hibernate ||
+ (driver_state_handler->on_hibernate &&
+ driver_state_handler->on_hibernate(session) == SWITCH_STATUS_SUCCESS &&
+ midstate == switch_channel_get_state(session->channel))) {
+
+ while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
+ if (!application_state_handler || !application_state_handler->on_hibernate ||
+ (application_state_handler->on_hibernate &&
+ application_state_handler->on_hibernate(session) == SWITCH_STATUS_SUCCESS &&
+ midstate == switch_channel_get_state(session->channel))) {
+ proceed++;
+ continue;
+ } else {
+ proceed = 0;
+ break;
+ }
+ }
+ index = 0;
+ while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
+ if (!application_state_handler || !application_state_handler->on_hibernate ||
+ (application_state_handler->on_hibernate &&
+ application_state_handler->on_hibernate(session) == SWITCH_STATUS_SUCCESS &&
+ midstate == switch_channel_get_state(session->channel))) {
+ proceed++;
+ continue;
+ } else {
+ proceed = 0;
+ break;
+ }
+ }
+ if (proceed) {
+ switch_core_standard_on_hibernate(session);
+ }
+ }
+ break;
}
if (midstate == CS_DONE) {
apr_ssize_t hlen = APR_HASH_KEY_STRING;
unsigned long CMD_EXECUTE = apr_hashfunc_default("execute", &hlen);
unsigned long CMD_HANGUP = apr_hashfunc_default("hangup", &hlen);
-
+ unsigned long CMD_NOMEDIA = apr_hashfunc_default("nomedia", &hlen);
+
assert(channel != NULL);
hlen = (switch_size_t) strlen(cmd);
cmd_hash = apr_hashfunc_default(cmd, &hlen);
+ switch_channel_set_flag(channel, CF_EVENT_PARSE);
+
if (!switch_strlen_zero(cmd)) {
if (cmd_hash == CMD_EXECUTE) {
const switch_application_interface_t *application_interface;
}
switch_channel_hangup(channel, cause);
- }
+ } else if (cmd_hash == CMD_NOMEDIA) {
+ char *uuid = switch_event_get_header(event, "nomedia-uuid");
+ switch_ivr_nomedia(uuid, SMF_REBRIDGE);
+ }
}
+
+ switch_channel_clear_flag(channel, CF_EVENT_PARSE);
+
}
SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session)
}
if (switch_channel_test_flag(chan_a, CF_TRANSFER)) {
+ switch_channel_clear_flag(chan_a, CF_HOLD);
+ switch_channel_clear_flag(chan_a, CF_SUSPEND);
break;
}
-
+
if (switch_core_session_dequeue_private_event(session_a, &event) == SWITCH_STATUS_SUCCESS) {
- switch_channel_set_flag(chan_b, CF_HOLD);
+ switch_channel_set_flag(chan_b, CF_SUSPEND);
switch_ivr_parse_event(session_a, event);
- switch_channel_clear_flag(chan_b, CF_HOLD);
+ switch_channel_clear_flag(chan_b, CF_SUSPEND);
switch_event_destroy(&event);
}
char dtmf[128];
switch_channel_dequeue_dtmf(chan_a, dtmf, sizeof(dtmf));
switch_core_session_send_dtmf(session_b, dtmf);
-
+
if (input_callback) {
if (input_callback(session_a, dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s ended call via DTMF\n", switch_channel_get_name(chan_a));
continue;
}
+
+ if (switch_channel_test_flag(chan_a, CF_SUSPEND) || switch_channel_test_flag(chan_b, CF_SUSPEND)) {
+ switch_yield(10000);
+ continue;
+ }
+
/* read audio from 1 channel and write it to the other */
status = switch_core_session_read_frame(session_a, &read_frame, -1, stream_id);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CUSTOM TRANSMIT\n");
switch_channel_clear_state_handler(channel, NULL);
+
if (!switch_channel_test_flag(channel, CF_ORIGINATOR)) {
switch_channel_set_flag(channel, CF_TAGGED);
return SWITCH_STATUS_FALSE;
uint8_t ready_a, ready_b;
switch_caller_profile_t *profile, *new_profile;
+
switch_channel_clear_flag(channel, CF_TRANSFER);
switch_channel_set_private(channel, "_uuid_bridge_", NULL);
mystate = switch_channel_get_state(channel);
}
- switch_channel_clear_flag(other_channel, CF_TRANSFER|CF_TAGGED);
-
+ switch_channel_clear_flag(other_channel, CF_TRANSFER);
+ switch_channel_clear_flag(other_channel, CF_TAGGED);
+
switch_core_session_reset(session);
switch_core_session_reset(other_session);
notready:
- if (!switch_channel_ready(caller_channel)) {
+ if (caller_channel && !switch_channel_ready(caller_channel)) {
idx = IDX_CANCEL;
}
}
if (caller_channel) {
- 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);
- }
-
if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
switch_channel_answer(caller_channel);
} else if (switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) {
return status;
}
+SWITCH_DECLARE(switch_status_t) switch_ivr_hold(switch_core_session_t *session)
+{
+ switch_core_session_message_t msg = {0};
+ switch_channel_t *channel;
+
+ msg.message_id = SWITCH_MESSAGE_INDICATE_HOLD;
+ msg.from = __FILE__;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ switch_channel_set_flag(channel, CF_HOLD);
+ switch_channel_set_flag(channel, CF_SUSPEND);
+
+ switch_core_session_receive_message(session, &msg);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_hold_uuid(char *uuid)
+{
+ switch_core_session_t *session;
+
+ if ((session = switch_core_session_locate(uuid))) {
+ switch_ivr_hold(session);
+ switch_core_session_rwunlock(session);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_unhold(switch_core_session_t *session)
+{
+ switch_core_session_message_t msg = {0};
+ switch_channel_t *channel;
+
+ msg.message_id = SWITCH_MESSAGE_INDICATE_UNHOLD;
+ msg.from = __FILE__;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ switch_channel_clear_flag(channel, CF_HOLD);
+ switch_channel_clear_flag(channel, CF_SUSPEND);
+
+ switch_core_session_receive_message(session, &msg);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_unhold_uuid(char *uuid)
+{
+ switch_core_session_t *session;
+
+ if ((session = switch_core_session_locate(uuid))) {
+ switch_ivr_unhold(session);
+ switch_core_session_rwunlock(session);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, switch_media_flag_t flags)
+{
+ switch_channel_t *channel;
+ uint8_t nomedia;
+ switch_core_session_t *session;
+ switch_event_t *event;
+ switch_core_session_t *other_session;
+ char *other_uuid = NULL;
+
+ if ((session = switch_core_session_locate(uuid))) {
+ char *app;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ if ((nomedia = switch_channel_test_flag(channel, CF_NOMEDIA))) {
+ switch_ivr_media(uuid, SMF_REBRIDGE);
+ }
+
+ if (!strncasecmp(path, "speak:", 6)) {
+ path += 6;
+ app = "speak";
+ } else {
+ app = "playback";
+ }
+
+ if ((flags & SMF_ECHO_BRIDGED) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE))
+ && (other_session = switch_core_session_locate(other_uuid))) {
+ if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-name", app);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-arg", "%s", path);
+ switch_core_session_queue_private_event(other_session, &event);
+ }
+ switch_core_session_rwunlock(other_session);
+ other_session = NULL;
+ }
+
+ if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-name", app);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-arg", "%s", path);
+ switch_core_session_queue_private_event(session, &event);
+ }
+
+ if (nomedia) {
+ if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "call-command", "nomedia");
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "nomedia-uuid", "%s", uuid);
+ switch_core_session_queue_private_event(session, &event);
+ }
+ }
+
+ switch_core_session_rwunlock(session);
+ }
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_media(char *uuid, switch_media_flag_t flags)
+{
+ char *other_uuid = NULL;
+ switch_channel_t *channel, *other_channel = NULL;
+ switch_core_session_t *session, *other_session;
+ switch_core_session_message_t msg = {0};
+ switch_status_t status = SWITCH_STATUS_GENERR;
+
+ msg.message_id = SWITCH_MESSAGE_INDICATE_MEDIA;
+ msg.from = __FILE__;
+
+ if ((session = switch_core_session_locate(uuid))) {
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ if (switch_channel_test_flag(channel, CF_NOMEDIA)) {
+ status = SWITCH_STATUS_SUCCESS;
+ switch_channel_clear_flag(channel, CF_NOMEDIA);
+ switch_core_session_receive_message(session, &msg);
+ if ((flags & SMF_REBRIDGE) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE))
+ && (other_session = switch_core_session_locate(other_uuid))) {
+ other_channel = switch_core_session_get_channel(other_session);
+ assert(other_channel != NULL);
+ switch_core_session_receive_message(other_session, &msg);
+ switch_channel_clear_state_handler(other_channel, NULL);
+ switch_core_session_rwunlock(other_session);
+ }
+ if (other_channel) {
+ switch_channel_clear_state_handler(channel, NULL);
+ }
+ }
+
+ switch_core_session_rwunlock(session);
+
+ if (other_channel) {
+ switch_ivr_uuid_bridge(uuid, other_uuid);
+ }
+ }
+
+ return status;
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_nomedia(char *uuid, switch_media_flag_t flags)
+{
+ char *other_uuid;
+ switch_channel_t *channel, *other_channel = NULL;
+ switch_core_session_t *session, *other_session = NULL;
+ switch_core_session_message_t msg = {0};
+ switch_status_t status = SWITCH_STATUS_GENERR;
+
+ msg.message_id = SWITCH_MESSAGE_INDICATE_NOMEDIA;
+ msg.from = __FILE__;
+
+ if ((session = switch_core_session_locate(uuid))) {
+ status = SWITCH_STATUS_SUCCESS;
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+ if (!switch_channel_test_flag(channel, CF_NOMEDIA)) {
+ switch_channel_set_flag(channel, CF_NOMEDIA);
+ switch_core_session_receive_message(session, &msg);
+ if ((flags & SMF_REBRIDGE) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) &&
+ (other_session = switch_core_session_locate(other_uuid))) {
+ other_channel = switch_core_session_get_channel(other_session);
+ assert(other_channel != NULL);
+ switch_core_session_receive_message(other_session, &msg);
+ switch_channel_clear_state_handler(other_channel, NULL);
+
+ }
+ if (other_channel) {
+ switch_channel_clear_state_handler(channel, NULL);
+ switch_ivr_signal_bridge(session, other_session);
+ switch_core_session_rwunlock(other_session);
+ }
+ }
+ switch_core_session_rwunlock(session);
+ }
+
+ return status;
+}
+
+static switch_status_t signal_bridge_on_hibernate(switch_core_session_t *session)
+{
+ switch_channel_t *channel = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+ switch_channel_clear_flag(channel, CF_TRANSFER);
+
+ switch_channel_set_variable(channel, SWITCH_BRIDGE_VARIABLE, switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE));
+
+ return SWITCH_STATUS_SUCCESS;
+}
static switch_status_t signal_bridge_on_hangup(switch_core_session_t *session)
{
}
- if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
+ if ((uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
switch_channel_t *other_channel = NULL;
other_channel = switch_core_session_get_channel(other_session);
switch_core_session_rwunlock(other_session);
}
+
return SWITCH_STATUS_SUCCESS;
}
/*.on_hangup */ signal_bridge_on_hangup,
/*.on_loopback */ NULL,
/*.on_transmit */ NULL,
- /*.on_hold */ NULL
+ /*.on_hold */ NULL,
+ /*.on_hibernate*/ signal_bridge_on_hibernate
};
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_event_fire(&event);
}
- switch_channel_set_state(caller_channel, CS_TRANSMIT);
- switch_channel_set_state(peer_channel, CS_TRANSMIT);
+ switch_channel_set_state_flag(caller_channel, CF_TRANSFER);
+ switch_channel_set_state_flag(peer_channel, CF_TRANSFER);
+
+
+ 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_set_state(caller_channel, CS_HIBERNATE);
+ switch_channel_set_state(peer_channel, CS_HIBERNATE);
return SWITCH_STATUS_SUCCESS;
}
switch_channel_event_set_data(caller_channel, event);
switch_event_fire(&event);
}
-
if (switch_channel_get_state(caller_channel) != CS_EXECUTE && !switch_channel_test_flag(caller_channel, CF_TRANSFER)) {
switch_channel_hangup(caller_channel, SWITCH_CAUSE_NORMAL_CLEARING);
}
switch_channel_add_state_handler(originatee_channel, &uuid_bridge_state_handlers);
switch_channel_set_private(originator_channel, "_uuid_bridge_", originatee_session);
- /* switch_channel_set_state_flag sets flags you want to be set when the next stat change happens */
+ /* switch_channel_set_state_flag sets flags you want to be set when the next state change happens */
switch_channel_set_state_flag(originator_channel, CF_TRANSFER);
switch_channel_set_state_flag(originatee_channel, CF_TRANSFER);
switch_channel_t *channel;
switch_caller_profile_t *profile, *new_profile;
switch_core_session_message_t msg = {0};
+ switch_core_session_t *other_session;
+ char *uuid = NULL;
assert(session != NULL);
assert(extension != NULL);
context = new_profile->context;
}
+ 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_set_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE, NULL);
+ switch_channel_set_variable(other_channel, SWITCH_SIGNAL_BRIDGE_VARIABLE, NULL);
+
+ switch_channel_hangup(other_channel, SWITCH_CAUSE_BLIND_TRANSFER);
+ switch_ivr_media(uuid, SMF_NONE);
+
+ switch_core_session_rwunlock(other_session);
+ }
+
switch_channel_set_caller_profile(channel, new_profile);
switch_channel_set_flag(channel, CF_TRANSFER);
switch_channel_set_state(channel, CS_RING);
char *ptr;
int quot = 0;
char qc = '"';
+ char *e;
+ int x;
if (!buf || !array || !arraylen) {
return 0;
}
if (*ptr) {
- char *e;
- if (*ptr == qc) {
- ptr++;
- }
- if ((e = strchr(ptr, qc))) {
- *e = '\0';
- }
array[argc++] = ptr;
}
+ /* strip quotes */
+ for(x = 0; x < argc; x++) {
+ if (*(array[x]) == qc) {
+ (array[x])++;
+ if ((e = strchr(array[x], qc))) {
+ *e = '\0';
+ }
+ }
+ }
+
return argc;
}