From fe3e99423782a31d145f8fe27d5cfad2e99f82ae Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 22 Feb 2006 02:50:33 +0000 Subject: [PATCH] adding some inter channel communication and other code for real-world usage (not totally done) git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@646 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_caller.h | 4 ++ src/include/switch_channel.h | 8 +++ src/include/switch_types.h | 26 ++++--- .../mod_bridgecall/mod_bridgecall.c | 26 ++++++- src/mod/endpoints/mod_exosip/mod_exosip.c | 71 ++++++++++++++++--- src/mod/endpoints/mod_iax/mod_iax.c | 9 ++- .../endpoints/mod_portaudio/mod_portaudio.c | 12 ++-- src/mod/endpoints/mod_wanpipe/mod_wanpipe.c | 47 +++++++++++- src/mod/endpoints/mod_woomera/mod_woomera.c | 8 ++- src/switch_caller.c | 2 + src/switch_channel.c | 17 +++++ 11 files changed, 194 insertions(+), 36 deletions(-) diff --git a/src/include/switch_caller.h b/src/include/switch_caller.h index 2e2a1388d4..3a1592aadd 100644 --- a/src/include/switch_caller.h +++ b/src/include/switch_caller.h @@ -76,6 +76,10 @@ extern "C" { char *ani2; /*! Destination Number */ char *destination_number; + /*! channel name */ + char *chan_name; + /*! unique id */ + char *uuid; }; /*! \brief An Abstract Representation of a dialplan Application */ diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 5b76232f50..595014edc8 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -129,6 +129,14 @@ SWITCH_DECLARE(void) switch_channel_set_originatee_caller_profile(switch_channel */ 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 diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 95692db7fc..af2c4f070b 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -64,13 +64,15 @@ typedef enum { \enum switch_core_session_message_t \brief Possible types of messages for inter-session communication
-	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 
 
*/ typedef enum { SWITCH_MESSAGE_REDIRECT_AUDIO, - SWITCH_MESSAGE_TRANSMIT_TEXT + SWITCH_MESSAGE_TRANSMIT_TEXT, + SWITCH_MESSAGE_INDICATE_PROGRESS } switch_core_session_message_t; @@ -171,18 +173,20 @@ typedef enum { \brief Channel Flags
-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 
 
*/ 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; diff --git a/src/mod/applications/mod_bridgecall/mod_bridgecall.c b/src/mod/applications/mod_bridgecall/mod_bridgecall.c index ea5075965b..884c53bc01 100644 --- a/src/mod/applications/mod_bridgecall/mod_bridgecall.c +++ b/src/mod/applications/mod_bridgecall/mod_bridgecall.c @@ -47,8 +47,8 @@ static void *audio_bridge_thread(switch_thread *thread, void *obj) { 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; @@ -64,6 +64,11 @@ static void *audio_bridge_thread(switch_thread *thread, void *obj) 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); @@ -76,6 +81,15 @@ static void *audio_bridge_thread(switch_thread *thread, void *obj) 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)); @@ -229,12 +243,18 @@ static void audio_bridge_function(switch_core_session *session, char *data) 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); diff --git a/src/mod/endpoints/mod_exosip/mod_exosip.c b/src/mod/endpoints/mod_exosip/mod_exosip.c index 995abdc89b..8b56889aef 100644 --- a/src/mod/endpoints/mod_exosip/mod_exosip.c +++ b/src/mod/endpoints/mod_exosip/mod_exosip.c @@ -63,7 +63,8 @@ typedef enum { 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; @@ -465,7 +466,7 @@ static switch_status exosip_answer_channel(switch_core_session *session) 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; @@ -666,6 +667,54 @@ static switch_status exosip_waitfor_write(switch_core_session *session, int ms, } +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, @@ -673,7 +722,9 @@ static const switch_io_routines exosip_io_routines = { /*.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 = { @@ -725,13 +776,15 @@ static switch_status exosip_outgoing_channel(switch_core_session *session, switc 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); @@ -806,6 +859,9 @@ static switch_status exosip_create_call(eXosip_event_t * event) 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, @@ -820,8 +876,7 @@ static switch_status exosip_create_call(eXosip_event_t * event) 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"); diff --git a/src/mod/endpoints/mod_iax/mod_iax.c b/src/mod/endpoints/mod_iax/mod_iax.c index 1fd251e3c7..de72c57b73 100644 --- a/src/mod/endpoints/mod_iax/mod_iax.c +++ b/src/mod/endpoints/mod_iax/mod_iax.c @@ -733,11 +733,13 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit 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); @@ -983,10 +985,11 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void) 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, diff --git a/src/mod/endpoints/mod_portaudio/mod_portaudio.c b/src/mod/endpoints/mod_portaudio/mod_portaudio.c index 7bd82e88d1..259ee185ac 100644 --- a/src/mod/endpoints/mod_portaudio/mod_portaudio.c +++ b/src/mod/endpoints/mod_portaudio/mod_portaudio.c @@ -498,13 +498,14 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit if (outbound_profile) { char name[128]; + snprintf(name, sizeof(name), "PortAudio/%s-%04x", + 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; - snprintf(name, sizeof(name), "PortAudio/%s-%04x", - caller_profile->destination_number ? caller_profile->destination_number : modname, - 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); @@ -812,11 +813,12 @@ static switch_status place_call(char *dest, char *out, size_t outlen) 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) { diff --git a/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c b/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c index d5ca077941..209f18c493 100644 --- a/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c +++ b/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c @@ -381,11 +381,12 @@ static switch_status wanpipe_outgoing_channel(switch_core_session *session, swit } } - + + 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)) { @@ -704,6 +705,43 @@ static int on_answer(struct sangoma_pri *spri, sangoma_pri_event_t event_type, p 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; @@ -770,6 +808,7 @@ static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri 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); @@ -867,8 +906,10 @@ static void *pri_thread_run(switch_thread *thread, void *obj) 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); diff --git a/src/mod/endpoints/mod_woomera/mod_woomera.c b/src/mod/endpoints/mod_woomera/mod_woomera.c index b590b14710..c22d569aab 100644 --- a/src/mod/endpoints/mod_woomera/mod_woomera.c +++ b/src/mod/endpoints/mod_woomera/mod_woomera.c @@ -490,11 +490,12 @@ static switch_status woomerachan_outgoing_channel(switch_core_session *session, 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); @@ -1067,10 +1068,11 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj) 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, diff --git a/src/switch_caller.c b/src/switch_caller.c index 156c28427b..266b1742af 100644 --- a/src/switch_caller.c +++ b/src/switch_caller.c @@ -68,6 +68,8 @@ SWITCH_DECLARE(switch_caller_profile *) switch_caller_profile_clone(switch_core_ 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; diff --git a/src/switch_channel.c b/src/switch_channel.c index 4f2ccf13f2..86086dd3b2 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -450,6 +450,16 @@ SWITCH_DECLARE(void) switch_channel_event_set_data(switch_channel *channel, swit 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; } @@ -479,6 +489,13 @@ SWITCH_DECLARE(switch_caller_profile *) switch_channel_get_originator_caller_pro 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);