[commit] r10471 - in freeswitch/trunk/src: include mod/applications/mod_commands mod/endpoints/mod_sofia
Author: anthm Date: Wed Nov 19 21:07:59 2008 New Revision: 10471 Log: wait for reply of refer Modified: freeswitch/trunk/src/include/switch_core.h freeswitch/trunk/src/include/switch_types.h freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c Modified: freeswitch/trunk/src/include/switch_core.h ============================================================================== --- freeswitch/trunk/src/include/switch_core.h (original) +++ freeswitch/trunk/src/include/switch_core.h Wed Nov 19 21:07:59 2008 @@ -92,6 +92,7 @@ const char *_file; const char *_func; int _line; + }; /*! \brief A generic object to pass as a thread's session object to allow mutiple arguements and a pool */ Modified: freeswitch/trunk/src/include/switch_types.h ============================================================================== --- freeswitch/trunk/src/include/switch_types.h (original) +++ freeswitch/trunk/src/include/switch_types.h Wed Nov 19 21:07:59 2008 @@ -676,7 +676,9 @@ } switch_text_channel_t; typedef enum { - SCSMF_DYNAMIC = (1 << 0) + SCSMF_DYNAMIC = (1 << 0), + SCSMF_FREE_STRING_REPLY = (1 << 1), + SCSMF_FREE_POINTER_REPLY = (1 << 2), } switch_core_session_message_flag_enum_t; typedef uint32_t switch_core_session_message_flag_t; Modified: freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c ============================================================================== --- freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c (original) +++ freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c Wed Nov 19 21:07:59 2008 @@ -1259,6 +1259,45 @@ return SWITCH_STATUS_SUCCESS; } + + +#define UUID_DEFLECT_SYNTAX "<uuid> <uri>" +SWITCH_STANDARD_API(uuid_deflect) +{ + switch_core_session_t *tsession = NULL; + char *uuid = NULL, *text = NULL; + + if (!switch_strlen_zero(cmd) && (uuid = strdup(cmd))) { + if ((text = strchr(uuid, ' '))) { + *text++ = '\0'; + } + } + + if (switch_strlen_zero(uuid) || switch_strlen_zero(text)) { + stream->write_function(stream, "-USAGE: %s\n", UUID_DEFLECT_SYNTAX); + } else { + if ((tsession = switch_core_session_locate(uuid))) { + switch_core_session_message_t msg = { 0 }; + + /* Tell the channel to deflect the call */ + msg.from = __FILE__; + msg.string_arg = text; + msg.message_id = SWITCH_MESSAGE_INDICATE_DEFLECT; + switch_core_session_receive_message(tsession, &msg); + stream->write_function(stream, "+OK:%s\n", msg.string_reply); + if (switch_set_flag((&msg), SCSMF_FREE_STRING_REPLY)) { + free(msg.string_reply); + } + switch_core_session_rwunlock(tsession); + } else { + stream->write_function(stream, "-ERR No Such Channel %s!\n", uuid); + } + } + + switch_safe_free(uuid); + return SWITCH_STATUS_SUCCESS; +} + #define SCHED_TRANSFER_SYNTAX "[+]<time> <uuid> <extension> [<dialplan>] [<context>]" SWITCH_STANDARD_API(sched_transfer_function) { @@ -3091,6 +3130,7 @@ SWITCH_ADD_API(commands_api_interface, "regex", "Eval a regex", regex_function, "<data>|<pattern>[|<subst string>]"); SWITCH_ADD_API(commands_api_interface, "acl", "compare an ip to an acl list", acl_function, "<ip> <list_name>"); SWITCH_ADD_API(commands_api_interface, "uuid_chat", "Send a chat message", uuid_chat, UUID_CHAT_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "uuid_deflect", "Send a deflect", uuid_deflect, UUID_DEFLECT_SYNTAX); SWITCH_ADD_API(commands_api_interface, "find_user_xml", "find a user", find_user_function, "<key> <user> <domain>"); SWITCH_ADD_API(commands_api_interface, "user_exists", "find a user", user_exists_function, "<key> <user> <domain>"); SWITCH_ADD_API(commands_api_interface, "xml_locate", "find some xml", xml_locate_function, "[root | <section> <tag> <tag_attr_name> <tag_attr_val>]"); Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c Wed Nov 19 21:07:59 2008 @@ -1120,6 +1120,7 @@ case SWITCH_MESSAGE_INDICATE_DEFLECT: { char ref_to[128] = ""; + const char *var; if (!strstr(msg->string_arg, "sip:")) { const char *format = strchr(tech_pvt->profile->sipip, ':') ? "sip:%s@[%s]" : "sip:%s@%s"; @@ -1128,6 +1129,16 @@ switch_set_string(ref_to, msg->string_arg); } nua_refer(tech_pvt->nh, SIPTAG_REFER_TO_STR(ref_to), SIPTAG_REFERRED_BY_STR(tech_pvt->contact_url), TAG_END()); + switch_mutex_unlock(tech_pvt->sofia_mutex); + sofia_wait_for_reply(tech_pvt, 9999, 300); + switch_mutex_lock(tech_pvt->sofia_mutex); + + if ((var = switch_channel_get_variable(tech_pvt->channel, "sip_refer_reply"))) { + msg->string_reply = strdup(var); + switch_set_flag(msg, SCSMF_FREE_STRING_REPLY); + } else { + msg->string_reply = "no reply"; + } } break; Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h Wed Nov 19 21:07:59 2008 @@ -513,6 +513,7 @@ switch_size_t last_ts; uint32_t check_frames; uint32_t mismatch_count; + nua_event_t want_event; }; struct callback_t { @@ -717,3 +718,4 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly); const char * sofia_state_string(int state); switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force); +void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout); Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c ============================================================================== --- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c (original) +++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c Wed Nov 19 21:07:59 2008 @@ -83,6 +83,7 @@ nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[]) { switch_channel_t *channel = NULL; + private_object_t *tech_pvt = NULL; /* make sure we have a proper event */ if (!sip || !sip->sip_event) { @@ -94,14 +95,35 @@ nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END()); return; } + + if (session) { + channel = switch_core_session_get_channel(session); + switch_assert(channel != NULL); + tech_pvt = switch_core_session_get_private(session); + switch_assert(tech_pvt != NULL); + } + + if (!strcasecmp(sip->sip_event->o_type, "refer")) { + if (session && channel && tech_pvt) { + if (sip->sip_payload && sip->sip_payload->pl_data) { + if (!switch_stristr("100", sip->sip_payload->pl_data)) { + switch_channel_set_variable(channel, "sip_refer_reply", sip->sip_payload->pl_data); + if (tech_pvt->want_event == 9999) { + tech_pvt->want_event = 0; + } + } + } + } + nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END()); + } + /* make sure we have a proper "talk" event */ if (!session || strcasecmp(sip->sip_event->o_type, "talk")) { goto error; } - channel = switch_core_session_get_channel(session); - switch_assert(channel != NULL); + if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { switch_channel_answer(channel); switch_channel_set_variable(channel, "auto_answer_destination", switch_channel_get_variable(channel, "destination_number")); @@ -109,6 +131,7 @@ nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END()); return; } + error: nua_respond(nh, 481, "Subscription Does Not Exist", NUTAG_WITH_THIS(nua), TAG_END()); @@ -160,6 +183,18 @@ { } +void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout) +{ + time_t exp = switch_timestamp(NULL) + timeout; + + tech_pvt->want_event = event; + + while(switch_channel_ready(tech_pvt->channel) && tech_pvt->want_event && switch_timestamp(NULL) < exp) { + switch_yield(100000); + } + +} + void sofia_event_callback(nua_event_t event, int status, char const *phrase, @@ -336,6 +371,10 @@ done: + if (tech_pvt && tech_pvt->want_event && event == tech_pvt->want_event) { + tech_pvt->want_event = 0; + } + switch (event) { case nua_i_subscribe: break; @@ -586,6 +625,7 @@ TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("include-session-description")), TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("presence.winfo")), TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("message-summary")), + NUTAG_ALLOW_EVENTS("refer"), SIPTAG_SUPPORTED_STR(supported), SIPTAG_USER_AGENT_STR(profile->user_agent), TAG_END()); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set params for %s\n", profile->name); @@ -2940,6 +2980,7 @@ } /*---------------------------------------*/ + void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, switch_core_session_t *session, sip_t const *sip, tagi_t tags[]) { /* Incoming refer */
participants (1)
-
FreeSWITCH SVN