char *ani2;
/*! Destination Number */
char *destination_number;
+ /*! channel name */
+ char *chan_name;
+ /*! unique id */
+ char *uuid;
};
/*! \brief An Abstract Representation of a dialplan Application */
*/
SWITCH_DECLARE(switch_caller_profile *) switch_channel_get_originatee_caller_profile(switch_channel *channel);
+
+/*!
+ \brief Retrive the given channel's unique id
+ \param channel channel to retrive the unique id from
+ \return the unique id
+*/
+SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel *channel);
+
/*!
\brief Set a variable on a given channel
\param channel channel to set variable on
\enum switch_core_session_message_t
\brief Possible types of messages for inter-session communication
<pre>
- SWITCH_MESSAGE_REDIRECT_AUDIO - Indication to redirect audio to another location if possible
- SWITCH_MESSAGE_TRANSMIT_TEXT - A text message
+ SWITCH_MESSAGE_REDIRECT_AUDIO - Indication to redirect audio to another location if possible
+ SWITCH_MESSAGE_TRANSMIT_TEXT - A text message
+ SWITCH_MESSAGE_INDICATE_PROGRESS - indicate progress
</pre>
*/
typedef enum {
SWITCH_MESSAGE_REDIRECT_AUDIO,
- SWITCH_MESSAGE_TRANSMIT_TEXT
+ SWITCH_MESSAGE_TRANSMIT_TEXT,
+ SWITCH_MESSAGE_INDICATE_PROGRESS
} switch_core_session_message_t;
\brief Channel Flags
<pre>
-CF_SEND_AUDIO = (1 << 0) - Channel will send audio
-CF_RECV_AUDIO = (1 << 1) - Channel will receive audio
-CF_ANSWERED = (1 << 2) - Channel is answered
-CF_OUTBOUND = (1 << 3) - Channel is an outbound channel
+CF_SEND_AUDIO = (1 << 0) - Channel will send audio
+CF_RECV_AUDIO = (1 << 1) - Channel will receive audio
+CF_ANSWERED = (1 << 2) - Channel is answered
+CF_OUTBOUND = (1 << 3) - Channel is an outbound channel
+CF_EARLY_MEDIA = (1 << 4) - Channel is ready for audio before answer
</pre>
*/
typedef enum {
- CF_SEND_AUDIO = (1 << 0),
- CF_RECV_AUDIO = (1 << 1),
- CF_ANSWERED = (1 << 2),
- CF_OUTBOUND = (1 << 3),
+ CF_SEND_AUDIO = (1 << 0),
+ CF_RECV_AUDIO = (1 << 1),
+ CF_ANSWERED = (1 << 2),
+ CF_OUTBOUND = (1 << 3),
+ CF_EARLY_MEDIA = (1 << 4)
} switch_channel_flag;
{
struct switch_core_thread_session *data = obj;
int *stream_id_p;
- int stream_id = 0;
-
+ int stream_id = 0, ans_a = 0, ans_b = 0;
+
switch_channel *chan_a, *chan_b;
switch_frame *read_frame;
switch_core_session *session_a, *session_b;
chan_a = switch_core_session_get_channel(session_a);
chan_b = switch_core_session_get_channel(session_b);
+
+ ans_a = switch_channel_test_flag(chan_a, CF_ANSWERED);
+ ans_b = switch_channel_test_flag(chan_b, CF_ANSWERED);
+
+
while (data->running > 0) {
switch_channel_state b_state = switch_channel_get_state(chan_b);
break;
}
+
+ if (!ans_b && switch_channel_test_flag(chan_a, CF_ANSWERED)) {
+ switch_channel_answer(chan_b);
+ }
+
+ if (!ans_a && switch_channel_test_flag(chan_b, CF_ANSWERED)) {
+ switch_channel_answer(chan_a);
+ }
+
if (switch_channel_has_dtmf(chan_a)) {
char dtmf[128];
switch_channel_dequeue_dtmf(chan_a, dtmf, sizeof(dtmf));
time(&start);
while (switch_channel_get_state(caller_channel) == CS_EXECUTE &&
switch_channel_get_state(peer_channel) == CS_TRANSMIT &&
- !switch_channel_test_flag(peer_channel, CF_ANSWERED) && ((time(NULL) - start) < timelimit)) {
+ !switch_channel_test_flag(peer_channel, CF_ANSWERED) &&
+ !switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA) &&
+ ((time(NULL) - start) < timelimit)) {
switch_yield(20000);
}
if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
switch_channel_answer(caller_channel);
+ }
+
+ if (switch_channel_test_flag(peer_channel, CF_ANSWERED) ||
+ switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) {
switch_core_session_launch_thread(session, audio_bridge_thread, (void *) &other_audio_thread);
audio_bridge_thread(NULL, (void *) &this_audio_thread);
TFLAG_USING_CODEC = (1 << 6),
TFLAG_RTP = (1 << 7),
TFLAG_BYE = (1 << 8),
- TFLAG_ANS = (1 << 9)
+ TFLAG_ANS = (1 << 9),
+ TFLAG_EARLY_MEDIA = (1 << 10)
} TFLAGS;
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
- if (!switch_test_flag(tech_pvt, TFLAG_ANS) && !switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (!switch_test_flag(tech_pvt, TFLAG_ANS) && !switch_channel_test_flag(channel, CF_OUTBOUND) ) {
char *buf = NULL;
osip_message_t *answer = NULL;
}
+static switch_status exosip_send_dtmf(switch_core_session *session, char *digits)
+{
+ return SWITCH_STATUS_FALSE;
+}
+
+static switch_status exosip_receive_message(switch_core_session *session, switch_core_session_message *msg)
+{
+
+ switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_PROGRESS:
+ if (msg) {
+ struct private_object *tech_pvt;
+ switch_channel *channel = NULL;
+
+ 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)) {
+ char *buf = NULL;
+ osip_message_t *progress = NULL;
+
+ switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Asked to send early media by %s\n", msg->from);
+
+ /* Transmit 183 Progress with SDP */
+ eXosip_lock();
+ eXosip_call_build_answer(tech_pvt->tid, 183, &progress);
+ sdp_message_to_str(tech_pvt->local_sdp, &buf);
+ osip_message_set_body(progress, buf, strlen(buf));
+ osip_message_set_content_type(progress, "application/sdp");
+ free(buf);
+ eXosip_call_send_answer(tech_pvt->tid, 183, progress);
+ eXosip_unlock();
+ switch_set_flag(tech_pvt, TFLAG_EARLY_MEDIA);
+ switch_channel_set_flag(channel, CF_EARLY_MEDIA);
+ }
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
static const switch_io_routines exosip_io_routines = {
/*.outgoing_channel */ exosip_outgoing_channel,
/*.answer_channel */ exosip_answer_channel,
/*.write_frame */ exosip_write_frame,
/*.kill_channel */ exosip_kill_channel,
/*.waitfor_read */ exosip_waitfor_read,
- /*.waitfor_read */ exosip_waitfor_write
+ /*.waitfor_read */ exosip_waitfor_write,
+ /*.send_dtmf*/ exosip_send_dtmf,
+ /*.receive_message*/ exosip_receive_message
};
static const switch_state_handler_table exosip_event_handlers = {
if (outbound_profile) {
char name[128];
- switch_caller_profile *caller_profile;
+ switch_caller_profile *caller_profile = NULL;
+
+ snprintf(name, sizeof(name), "Exosip/%s-%04x", outbound_profile->destination_number, rand() & 0xffff);
+ switch_channel_set_name(channel, name);
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+
switch_channel_set_caller_profile(channel, caller_profile);
tech_pvt->caller_profile = caller_profile;
- snprintf(name, sizeof(name), "Exosip/%s-%04x", caller_profile->destination_number, rand() & 0xffff);
- switch_channel_set_name(channel, name);
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Doh! no caller profile\n");
switch_core_session_destroy(new_session);
return SWITCH_STATUS_MEMERR;
}
+ snprintf(name, sizeof(name), "Exosip/%s-%04x", event->request->from->url->username, rand() & 0xffff);
+ switch_channel_set_name(channel, name);
+
if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
globals.dialplan,
event->request->from->displayname,
tech_pvt->cid = event->cid;
tech_pvt->tid = event->tid;
- snprintf(name, sizeof(name), "Exosip/%s-%04x", tech_pvt->caller_profile->destination_number, rand() & 0xffff);
- switch_channel_set_name(channel, name);
+
if ((remote_sdp = eXosip_get_sdp_info(event->request)) == 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Cannot Find Remote SDP!\n");
if (outbound_profile) {
char name[128];
+
+ snprintf(name, sizeof(name), "IAX/%s-%04x", outbound_profile->destination_number, rand() & 0xffff);
+ switch_channel_set_name(channel, name);
+
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
switch_channel_set_caller_profile(channel, caller_profile);
tech_pvt->caller_profile = caller_profile;
- snprintf(name, sizeof(name), "IAX/%s-%04x", caller_profile->destination_number, rand() & 0xffff);
- switch_channel_set_name(channel, name);
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Doh! no caller profile\n");
switch_core_session_destroy(new_session);
iaxevent->ies.calling_ani,
NULL, iaxevent->ies.called_number)) != 0) {
char name[128];
- switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
snprintf(name, sizeof(name), "IAX/%s-%04x", tech_pvt->caller_profile->destination_number,
rand() & 0xffff);
switch_channel_set_name(channel, name);
+ switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+
}
if (iax_set_codec(tech_pvt, iaxevent->session,
if (outbound_profile) {
char name[128];
- caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
- switch_channel_set_caller_profile(channel, caller_profile);
- tech_pvt->caller_profile = caller_profile;
snprintf(name, sizeof(name), "PortAudio/%s-%04x",
- caller_profile->destination_number ? caller_profile->destination_number : modname,
+ caller_profile->destination_number ? outbound_profile->destination_number : modname,
rand() & 0xffff);
switch_channel_set_name(channel, name);
+
+ caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+ switch_channel_set_caller_profile(channel, caller_profile);
+ tech_pvt->caller_profile = caller_profile;
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Doh! no caller profile\n");
switch_core_session_destroy(new_session);
globals.cid_name,
globals.cid_num, NULL, NULL, NULL, dest)) != 0) {
char name[128];
- switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
snprintf(name, sizeof(name), "PortAudio/%s-%04x",
tech_pvt->caller_profile->destination_number ? tech_pvt->caller_profile->
destination_number : modname, rand() & 0xffff);
switch_channel_set_name(channel, name);
+
+ switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
}
tech_pvt->session = session;
if ((status = engage_device(tech_pvt)) == SWITCH_STATUS_SUCCESS) {
}
}
-
+
+ snprintf(name, sizeof(name), "WanPipe/%s-%04x", caller_profile->destination_number, rand() & 0xffff);
+ switch_channel_set_name(channel, name);
switch_channel_set_caller_profile(channel, caller_profile);
tech_pvt->caller_profile = caller_profile;
- snprintf(name, sizeof(name), "WanPipe/%s-%04x", caller_profile->destination_number, rand() & 0xffff);
- switch_channel_set_name(channel, name);
+
do {
if ((spri = &SPANS[span]->spri)) {
return 0;
}
+
+static int on_proceed(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
+{
+ switch_core_session *session;
+ switch_channel *channel;
+ struct channel_map *chanmap;
+
+ chanmap = spri->private;
+
+ if ((session = chanmap->map[event->proceeding.channel])) {
+ switch_caller_profile *originator;
+
+ switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Proceeding on channel %d\n", event->proceeding.channel);
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ if ((originator = switch_channel_get_originator_caller_profile(channel))) {
+ switch_core_session_message msg;
+
+ switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Passing progress to Originator %s\n", originator->chan_name);
+
+ msg.message_id = SWITCH_MESSAGE_INDICATE_PROGRESS;
+ msg.from = switch_channel_get_name(channel);
+
+ switch_core_session_message_send(originator->uuid, &msg);
+
+ switch_channel_set_flag(channel, CF_EARLY_MEDIA);
+ }
+
+ //switch_channel_answer(channel);
+ } else {
+ switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Proceeding on channel %d but it's not in use?\n", event->proceeding.channel);
+ }
+
+ return 0;
+}
+
static int on_ringing(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
{
switch_core_session *session;
switch_core_session_set_private(session, tech_pvt);
sprintf(name, "w%dg%d", spri->span, event->ring.channel);
switch_channel_set_name(channel, name);
+
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n");
switch_core_session_destroy(&session);
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_RING, on_ring);
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_RINGING, on_ringing);
//SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_SETUP_ACK, on_ringing);
+ SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_PROCEEDING, on_proceed);
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_ANSWER, on_answer);
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_HANGUP_REQ, on_hangup);
+ SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_HANGUP, on_hangup);
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_INFO_RECEIVED, on_info);
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_RESTART, on_restart);
char name[128];
switch_caller_profile *caller_profile;
+ snprintf(name, sizeof(name), "Woomera/%s-%04x", outbound_profile->destination_number, rand() & 0xffff);
+ switch_channel_set_name(channel, name);
+
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
switch_channel_set_caller_profile(channel, caller_profile);
tech_pvt->caller_profile = caller_profile;
- snprintf(name, sizeof(name), "Woomera/%s-%04x", caller_profile->destination_number, rand() & 0xffff);
- switch_channel_set_name(channel, name);
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Doh! no caller profile\n");
switch_core_session_destroy(new_session);
tech_pvt->profile->dialplan,
cid_name, cid_num, ip, NULL, NULL, exten)) != 0) {
char name[128];
- switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
snprintf(name, sizeof(name), "Woomera/%s-%04x", tech_pvt->caller_profile->destination_number,
rand() & 0xffff);
switch_channel_set_name(channel, name);
+ switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+
}
woomera_printf(tech_pvt->profile, tech_pvt->command_channel,
profile->caller_id_number = switch_core_session_strdup(session, tocopy->caller_id_number);
profile->network_addr = switch_core_session_strdup(session, tocopy->network_addr);
profile->destination_number = switch_core_session_strdup(session, tocopy->destination_number);
+ profile->uuid = switch_core_session_strdup(session, tocopy->uuid);
+ profile->chan_name = switch_core_session_strdup(session, tocopy->chan_name);
}
return profile;
SWITCH_DECLARE(void) switch_channel_set_caller_profile(switch_channel *channel, switch_caller_profile *caller_profile)
{
assert(channel != NULL);
+ assert(channel->session != NULL);
+
+ if (!caller_profile->uuid) {
+ caller_profile->uuid = switch_core_session_strdup(channel->session, switch_core_session_get_uuid(channel->session));
+ }
+
+ if (!caller_profile->chan_name) {
+ caller_profile->chan_name = switch_core_session_strdup(channel->session, channel->name);
+ }
+
channel->caller_profile = caller_profile;
}
return channel->originator_caller_profile;
}
+SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel *channel)
+{
+ assert(channel != NULL);
+ assert(channel->session != NULL);
+ return switch_core_session_get_uuid(channel->session);
+}
+
SWITCH_DECLARE(switch_caller_profile *) switch_channel_get_originatee_caller_profile(switch_channel *channel)
{
assert(channel != NULL);