freeswitch/src/mod/endpoints/mod_sofia/mod_sofia.c

6497 lines
237 KiB
C
Raw Normal View History

/*
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
2014-02-05 21:02:28 +00:00
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
2016-01-22 22:43:23 +00:00
* Ken Rice <krice at freeswitch.org>
* Paul D. Tinsley <pdt at jackhammer.org>
* Bret McDanel <trixter AT 0xdecafbad.com>
2012-08-31 20:35:13 +00:00
* Raymond Chandler <intralanman@freeswitch.org>
* Emmanuel Schmidbauer <eschmidbauer@gmail.com>
* Kathleen King <kathleen.king@quentustech.com>
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
*
*
* mod_sofia.c -- SOFIA SIP Endpoint
*
*/
/* Best viewed in a 160 x 60 VT100 Terminal or so the line below at least fits across your screen*/
/*************************************************************************************************************************************************************/
#include "mod_sofia.h"
#include "sofia-sip/sip_extra.h"
2011-05-23 17:23:30 +00:00
SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown);
SWITCH_MODULE_DEFINITION(mod_sofia, mod_sofia_load, mod_sofia_shutdown, NULL);
struct mod_sofia_globals mod_sofia_globals;
switch_endpoint_interface_t *sofia_endpoint_interface;
Media Management (Sponsored By Front Logic) This modification makes it possible to change the media path of session in the switch on-the-fly and from the dialplan. It adds some API interface calls usable from a remote client such as mod_event_socket or the test console. 1) media [off] <uuid> Turns on/off the media on the call described by <uuid> The media will be redirected as desiered either into the switch or point to point. 2) hold [off] <uuid> Turns on/off endpoint specific hold state on the session described by <uuid> 3) broadcast <uuid> "<path>[ <timer_name>]" or "speak:<tts_engine>|<tts_voice>|<text>[|<timer_name>]" [both] A message will be sent to the call described by uuid instructing it to play the file or speak the text indicated. If the 'both' option is specified both ends of the call will hear the message otherwise just the uuid specified will hear the message. During playback when only one side is hearing the message the other end will hear silence. If media is not flowing across the switch when the message is broadcasted, the media will be directed to the switch for the duration of the call and then returned to it's previous state. Also the no_media=true option in the dialplan before a bridge makes it possible to place a call while proxying the session description from one endpoint to the other and establishing an immidiate point-to-point media connection with no media on the switch. <action application="set" data="no_media=true"/> <action application="bridge" data="sofia/mydomain.com/myid@myhost.com"/> *NOTE* when connecting two outbound legs by using the "originate" api command with an extension that has no_media=true enabled, the media for the first leg will be engaged with the switch until the second leg has answered and the other session description is available to establish a point to point connection at which time point-to-point mode will be enabled. *NOTE* it is reccommended you rebuild FreeSWITCH with "make sure" as there have been some changes to the core. git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3245 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-10-31 21:38:06 +00:00
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
#define STRLEN 15
void mod_sofia_shutdown_cleanup();
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
static switch_status_t sofia_on_init(switch_core_session_t *session);
static switch_status_t sofia_on_exchange_media(switch_core_session_t *session);
static switch_status_t sofia_on_soft_execute(switch_core_session_t *session);
static switch_status_t sofia_acknowledge_call(switch_core_session_t *session);
static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session,
switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
static switch_status_t sofia_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
static switch_status_t sofia_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
2016-07-11 03:25:14 +00:00
static switch_status_t sofia_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
static switch_status_t sofia_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
static switch_status_t sofia_kill_channel(switch_core_session_t *session, int sig);
/* BODY OF THE MODULE */
/*************************************************************************************************************************************************************/
/*
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
so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
*/
static switch_status_t sofia_on_init(switch_core_session_t *session)
{
const char *hval = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_assert(tech_pvt != NULL);
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
2012-12-22 00:06:09 +00:00
switch_mutex_lock(tech_pvt->sofia_mutex);
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
2012-12-22 00:06:09 +00:00
switch_core_media_check_dtmf_type(session);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SOFIA INIT\n", switch_channel_get_name(channel));
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
2012-12-22 00:06:09 +00:00
switch_core_media_absorb_sdp(session);
}
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
if ((hval = switch_channel_get_variable(channel, "sip_watch_headers"))) {
char *dupvar = NULL;
char *watch_headers[10];
unsigned int numhdrs = 0;
2015-08-31 21:08:52 +00:00
unsigned int i = 0;
dupvar = switch_core_session_strdup(session, hval);
numhdrs = switch_separate_string(dupvar, ',', watch_headers, switch_arraylen(watch_headers));
if (numhdrs) {
char **wheaders = switch_core_session_alloc(session, ((numhdrs+1) * sizeof(wheaders[0])));
for (i = 0; i < numhdrs; i++) {
wheaders[i] = watch_headers[i];
}
wheaders[i] = NULL;
tech_pvt->watch_headers = wheaders;
}
}
if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING) || switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING_BRIDGE)) {
sofia_set_flag(tech_pvt, TFLAG_RECOVERED);
}
if (sofia_test_flag(tech_pvt, TFLAG_OUTBOUND) || switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) {
if (sofia_glue_do_invite(session) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
assert(switch_channel_get_state(channel) != CS_INIT);
status = SWITCH_STATUS_FALSE;
goto end;
}
}
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
2010-06-30 15:35:03 +00:00
end:
switch_mutex_unlock(tech_pvt->sofia_mutex);
return status;
}
static switch_status_t sofia_on_routing(switch_core_session_t *session)
{
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_assert(tech_pvt != NULL);
if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_INVITE_100) &&
!switch_channel_test_flag(channel, CF_ANSWERED) &&
switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
if (sofia_acknowledge_call(session) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Call appears to be already acknowledged\n");
}
}
if (!sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_clear_flag(channel, CF_LEG_HOLDING);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SOFIA ROUTING\n",
switch_channel_get_name(switch_core_session_get_channel(session)));
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sofia_on_reset(switch_core_session_t *session)
{
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_assert(tech_pvt != NULL);
if (!sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_clear_flag(channel, CF_LEG_HOLDING);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SOFIA RESET\n",
switch_channel_get_name(switch_core_session_get_channel(session)));
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sofia_on_hibernate(switch_core_session_t *session)
{
private_object_t *tech_pvt = switch_core_session_get_private(session);
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_assert(tech_pvt != NULL);
if (!sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_clear_flag(channel, CF_LEG_HOLDING);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SOFIA HIBERNATE\n",
switch_channel_get_name(switch_core_session_get_channel(session)));
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sofia_on_execute(switch_core_session_t *session)
{
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_assert(tech_pvt != NULL);
if (!sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_clear_flag(channel, CF_LEG_HOLDING);
}
2013-10-15 21:24:32 +00:00
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SOFIA EXECUTE\n",
switch_channel_get_name(switch_core_session_get_channel(session)));
return SWITCH_STATUS_SUCCESS;
}
2010-10-06 13:38:32 +00:00
char *generate_pai_str(private_object_t *tech_pvt)
{
2010-10-06 13:38:32 +00:00
switch_core_session_t *session = tech_pvt->session;
const char *callee_name = NULL, *callee_number = NULL;
const char *var, *header, *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent");
char *pai = NULL;
2011-10-14 19:13:16 +00:00
const char *host = switch_channel_get_variable(tech_pvt->channel, "sip_to_host");
if (zstr(host)) {
host = tech_pvt->profile->sipip;
}
2010-10-06 13:38:32 +00:00
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_CALLEE_ID) || !sofia_test_pflag(tech_pvt->profile, PFLAG_CID_IN_1XX) ||
((var = switch_channel_get_variable(tech_pvt->channel, "sip_cid_in_1xx")) && switch_false(var))) {
return NULL;
}
2012-11-14 15:20:52 +00:00
if (zstr((callee_name = switch_channel_get_variable(tech_pvt->channel, "initial_callee_id_name"))) &&
zstr((callee_name = switch_channel_get_variable(tech_pvt->channel, "effective_callee_id_name"))) &&
zstr((callee_name = switch_channel_get_variable(tech_pvt->channel, "sip_callee_id_name")))) {
callee_name = switch_channel_get_variable(tech_pvt->channel, "callee_id_name");
}
2012-11-14 15:20:52 +00:00
if (zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "initial_callee_id_number"))) &&
zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "effective_callee_id_number"))) &&
2010-04-12 18:37:40 +00:00
zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "sip_callee_id_number"))) &&
zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "callee_id_number")))) {
2010-06-23 18:22:52 +00:00
callee_number = tech_pvt->caller_profile->destination_number;
}
if (zstr(callee_name) && !zstr(callee_number)) {
callee_name = callee_number;
}
callee_number = switch_sanitize_number(switch_core_session_strdup(session, callee_number));
callee_name = switch_sanitize_number(switch_core_session_strdup(session, callee_name));
if (!zstr(callee_number) && (zstr(ua) || !switch_stristr("polycom", ua))) {
2011-10-14 19:13:16 +00:00
callee_number = switch_core_session_sprintf(session, "sip:%s@%s", callee_number, host);
}
header = (tech_pvt->cid_type == CID_TYPE_RPID && !switch_stristr("aastra", ua)) ? "Remote-Party-ID" : "P-Asserted-Identity";
if (!zstr(callee_name) && strcmp(callee_name, "_undef_") && !zstr(callee_number)) {
2011-09-27 20:38:40 +00:00
check_decode(callee_name, tech_pvt->session);
if (switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote)) {
pai = switch_core_session_sprintf(tech_pvt->session, "%s: \"%s\" <%s>%s\n"
"X-FS-Display-Name: %s\nX-FS-Display-Number: %s\n",
header, callee_name, callee_number,
2013-08-15 16:19:51 +00:00
tech_pvt->cid_type == CID_TYPE_RPID && !switch_stristr("aastra", ua) ?
";party=calling;privacy=off;screen=no" : "",
callee_name, callee_number);
} else {
pai = switch_core_session_sprintf(tech_pvt->session, "%s: \"%s\" <%s>%s\n", header, callee_name, callee_number,
2013-08-15 16:19:51 +00:00
tech_pvt->cid_type == CID_TYPE_RPID && !switch_stristr("aastra", ua) ?
";party=calling;privacy=off;screen=no" : "");
}
}
return pai;
}
static switch_jb_t *sofia_get_jb(switch_core_session_t *session, switch_media_type_t type)
{
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
2012-12-22 00:06:09 +00:00
return switch_core_media_get_jb(tech_pvt->session, type);
}
/* map QSIG cause codes to SIP from RFC4497 section 8.4.1 */
static int hangup_cause_to_sip(switch_call_cause_t cause)
{
switch (cause) {
case SWITCH_CAUSE_UNALLOCATED_NUMBER:
case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
return 404;
case SWITCH_CAUSE_USER_BUSY:
return 486;
case SWITCH_CAUSE_NO_USER_RESPONSE:
return 408;
case SWITCH_CAUSE_NO_ANSWER:
case SWITCH_CAUSE_SUBSCRIBER_ABSENT:
return 480;
case SWITCH_CAUSE_CALL_REJECTED:
return 603;
case SWITCH_CAUSE_NUMBER_CHANGED:
case SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION:
return 410;
case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
2011-12-15 17:16:41 +00:00
case SWITCH_CAUSE_INVALID_PROFILE:
return 502;
case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
2011-12-15 17:16:41 +00:00
case SWITCH_CAUSE_INVALID_URL:
case SWITCH_CAUSE_INVALID_GATEWAY:
return 484;
case SWITCH_CAUSE_FACILITY_REJECTED:
return 501;
case SWITCH_CAUSE_NORMAL_UNSPECIFIED:
return 480;
case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL:
case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION:
case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
case SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE:
case SWITCH_CAUSE_SWITCH_CONGESTION:
2011-12-15 17:16:41 +00:00
case SWITCH_CAUSE_GATEWAY_DOWN:
return 503;
case SWITCH_CAUSE_OUTGOING_CALL_BARRED:
case SWITCH_CAUSE_INCOMING_CALL_BARRED:
case SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH:
return 403;
case SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL:
return 503;
case SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL:
case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
return 488;
case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
case SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED:
return 501;
case SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
return 504;
case SWITCH_CAUSE_ORIGINATOR_CANCEL:
return 487;
case SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR:
return 483;
/* Custom mappings not part of RFC */
case SWITCH_CAUSE_BUSY_EVERYWHERE:
return 600;
case SWITCH_CAUSE_DECLINE:
return 603;
case SWITCH_CAUSE_DOES_NOT_EXIST_ANYWHERE:
return 604;
case SWITCH_CAUSE_NOT_ACCEPTABLE:
return 606;
case SWITCH_CAUSE_UNWANTED:
return 607;
default:
return 480;
}
}
switch_status_t sofia_on_destroy(switch_core_session_t *session)
{
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SOFIA DESTROY\n", switch_channel_get_name(channel));
if (tech_pvt) {
if (tech_pvt->proxy_refer_msg) {
msg_ref_destroy(tech_pvt->proxy_refer_msg);
tech_pvt->proxy_refer_msg = NULL;
}
2012-08-06 21:12:03 +00:00
if (tech_pvt->respond_phrase) {
switch_yield(100000);
}
2012-09-01 16:46:45 +00:00
if (!zstr(tech_pvt->call_id)) {
switch_core_hash_delete_locked(tech_pvt->profile->chat_hash, tech_pvt->call_id, tech_pvt->profile->flag_mutex);
}
switch_mutex_lock(tech_pvt->profile->flag_mutex);
tech_pvt->profile->inuse--;
switch_mutex_unlock(tech_pvt->profile->flag_mutex);
2012-12-22 00:06:09 +00:00
switch_media_handle_destroy(session);
2010-06-23 18:22:52 +00:00
if (sofia_test_pflag(tech_pvt->profile, PFLAG_DESTROY) && !tech_pvt->profile->inuse) {
sofia_profile_destroy(tech_pvt->profile);
}
}
return SWITCH_STATUS_SUCCESS;
}
switch_status_t sofia_on_hangup(switch_core_session_t *session)
{
switch_core_session_t *a_session;
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_call_cause_t cause = switch_channel_get_cause(channel);
int sip_cause = hangup_cause_to_sip(cause);
const char *ps_cause = NULL, *use_my_cause;
const char *gateway_name = NULL;
sofia_gateway_t *gateway_ptr = NULL;
if ((gateway_name = switch_channel_get_variable(channel, "sip_gateway_name"))) {
gateway_ptr = sofia_reg_find_gateway(gateway_name);
}
2010-06-23 18:22:52 +00:00
2012-08-16 17:09:19 +00:00
if (!tech_pvt) {
return SWITCH_STATUS_SUCCESS;
}
switch_mutex_lock(tech_pvt->sofia_mutex);
if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
tech_pvt->profile->ob_failed_calls++;
} else {
tech_pvt->profile->ib_failed_calls++;
}
2010-06-23 18:22:52 +00:00
if (gateway_ptr) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
gateway_ptr->ob_failed_calls++;
} else {
gateway_ptr->ib_failed_calls++;
}
2010-06-23 18:22:52 +00:00
}
}
2010-06-23 18:22:52 +00:00
if (gateway_ptr) {
sofia_reg_release_gateway(gateway_ptr);
}
if (!((use_my_cause = switch_channel_get_variable(channel, "sip_ignore_remote_cause")) && switch_true(use_my_cause))) {
2012-01-16 18:45:25 +00:00
ps_cause = switch_channel_get_variable(channel, "last_bridge_" SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE);
}
if (!zstr(ps_cause) && (!strncasecmp(ps_cause, "sip:", 4) || !strncasecmp(ps_cause, "sips:", 5))) {
int new_cause = atoi(sofia_glue_strip_proto(ps_cause));
if (new_cause) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Overriding SIP cause %d with %d from the other leg\n",
switch_channel_get_name(channel), sip_cause, new_cause);
sip_cause = new_cause;
}
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Channel %s hanging up, cause: %s\n",
switch_channel_get_name(channel), switch_channel_cause2str(cause));
if (tech_pvt->hash_key && !sofia_test_pflag(tech_pvt->profile, PFLAG_DESTROY)) {
switch_core_hash_delete_locked(tech_pvt->profile->chat_hash, tech_pvt->hash_key, tech_pvt->profile->flag_mutex);
}
if (session && tech_pvt->profile->pres_type) {
char *sql = switch_mprintf("delete from sip_dialogs where uuid='%q'", switch_core_session_get_uuid(session));
switch_assert(sql);
sofia_glue_execute_sql_now(tech_pvt->profile, &sql, SWITCH_TRUE);
}
if (tech_pvt->kick && (a_session = switch_core_session_locate(tech_pvt->kick))) {
switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
switch_channel_hangup(a_channel, switch_channel_get_cause(channel));
switch_core_session_rwunlock(a_session);
}
if (sofia_test_pflag(tech_pvt->profile, PFLAG_DESTROY)) {
2010-06-23 18:22:52 +00:00
sofia_set_flag(tech_pvt, TFLAG_BYE);
} else if (tech_pvt->nh && !sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char reason[128] = "";
char *bye_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_BYE_HEADER_PREFIX);
const char *val = NULL;
2012-07-03 14:23:25 +00:00
const char *max_forwards = switch_channel_get_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE);
2013-04-05 05:38:57 +00:00
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
val = switch_channel_get_variable(tech_pvt->channel, "disable_q850_reason");
2011-10-25 13:47:01 +00:00
2012-01-06 18:18:57 +00:00
if (!val || switch_false(val)) {
2012-04-16 16:57:19 +00:00
if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_reason"))) {
2012-03-29 16:35:57 +00:00
switch_snprintf(reason, sizeof(reason), "%s", val);
} else {
if ((switch_channel_test_flag(channel, CF_INTERCEPT) || cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE)
&& !switch_true(switch_channel_get_variable(channel, "ignore_completed_elsewhere"))) {
2012-03-29 16:35:57 +00:00
switch_snprintf(reason, sizeof(reason), "SIP;cause=200;text=\"Call completed elsewhere\"");
} else if (cause > 0 && cause < 128) {
switch_snprintf(reason, sizeof(reason), "Q.850;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
} else {
2012-06-21 18:07:38 +00:00
switch_snprintf(reason, sizeof(reason), "SIP;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
2012-03-29 16:35:57 +00:00
}
}
}
if (switch_channel_test_flag(channel, CF_INTERCEPT) || cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE) {
switch_channel_set_variable(channel, "call_completed_elsewhere", "true");
}
if (switch_channel_test_flag(channel, CF_ANSWERED) || sofia_test_flag(tech_pvt, TFLAG_ANS)) {
if (!tech_pvt->got_bye) {
switch_channel_set_variable(channel, "sip_hangup_disposition", "send_bye");
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sending BYE to %s\n", switch_channel_get_name(channel));
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
nua_bye(tech_pvt->nh,
TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri)),
SIPTAG_CONTACT(SIP_NONE),
TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason)),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
} else {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sending CANCEL to %s\n", switch_channel_get_name(channel));
if (!tech_pvt->got_bye) {
switch_channel_set_variable(channel, "sip_hangup_disposition", "send_cancel");
switch_channel_set_variable(channel, "sip_invite_failure_status", "487");
switch_channel_set_variable(channel, "sip_invite_failure_phrase", "CANCEL");
}
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
nua_cancel(tech_pvt->nh,
SIPTAG_CONTACT(SIP_NONE),
2013-04-05 05:38:57 +00:00
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason)), TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
} else {
char *resp_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
const char *phrase;
2012-06-27 17:25:03 +00:00
char *added_headers = NULL;
if (tech_pvt->respond_phrase) {
2012-08-06 21:12:03 +00:00
//phrase = su_strdup(nua_handle_home(tech_pvt->nh), tech_pvt->respond_phrase);
phrase = tech_pvt->respond_phrase;
} else {
phrase = sip_status_phrase(sip_cause);
}
2012-07-03 14:23:25 +00:00
if (tech_pvt->respond_code) {
sip_cause = tech_pvt->respond_code;
switch (sip_cause) {
case 401:
case 407:
{
const char *to_host = switch_channel_get_variable(channel, "sip_challenge_realm");
2012-07-03 14:23:25 +00:00
if (zstr(to_host)) {
to_host = switch_channel_get_variable(channel, "sip_to_host");
2012-07-03 14:23:25 +00:00
}
2012-07-03 14:23:25 +00:00
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Challenging call\n");
sofia_reg_auth_challenge(tech_pvt->profile, tech_pvt->nh, NULL, REG_INVITE, to_host, 0, 0);
2012-07-03 14:23:25 +00:00
*reason = '\0';
}
break;
2012-07-03 14:23:25 +00:00
case 484:
{
const char *to = switch_channel_get_variable(channel, "sip_to_uri");
char *to_uri = NULL;
if (to) {
char *p;
to_uri = switch_core_session_sprintf(session, "sip:%s", to);
if ((p = strstr(to_uri, ":5060"))) {
*p = '\0';
}
2012-07-03 14:23:25 +00:00
tech_pvt->respond_dest = to_uri;
2012-07-03 14:23:25 +00:00
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Overlap Dial with %d %s\n", sip_cause, phrase);
2012-07-03 14:23:25 +00:00
}
break;
default:
break;
}
}
2012-06-27 17:25:03 +00:00
if (tech_pvt->respond_dest && !sofia_test_pflag(tech_pvt->profile, PFLAG_MANUAL_REDIRECT)) {
added_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_HEADER_PREFIX);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Responding to INVITE with: %d\n", sip_cause);
if (!tech_pvt->got_bye) {
switch_channel_set_variable(channel, "sip_hangup_disposition", "send_refuse");
}
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
2010-10-06 13:38:32 +00:00
char *cid = generate_pai_str(tech_pvt);
2010-06-30 15:35:03 +00:00
2011-06-08 23:50:21 +00:00
if (sip_cause > 299) {
switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38);
switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ);
switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_FAIL);
}
nua_respond(tech_pvt->nh, sip_cause, phrase,
TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)),
TAG_IF(!zstr(resp_headers), SIPTAG_HEADER_STR(resp_headers)),
TAG_IF(!zstr(added_headers), SIPTAG_HEADER_STR(added_headers)),
2012-06-27 17:25:03 +00:00
TAG_IF(tech_pvt->respond_dest, SIPTAG_CONTACT_STR(tech_pvt->respond_dest)),
TAG_IF(!zstr(max_forwards), SIPTAG_MAX_FORWARDS_STR(max_forwards)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
switch_safe_free(resp_headers);
}
2012-06-27 19:53:15 +00:00
switch_safe_free(added_headers);
}
}
sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
switch_safe_free(bye_headers);
}
if (cause == SWITCH_CAUSE_WRONG_CALL_STATE) {
switch_event_t *s_event;
if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_WRONG_CALL_STATE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from_user", tech_pvt->from_user);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network_ip", tech_pvt->mparams.remote_ip);
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "network_port", "%d", tech_pvt->mparams.remote_port);
switch_event_fire(&s_event);
}
}
sofia_clear_flag(tech_pvt, TFLAG_IO);
if (tech_pvt->sofia_private) {
/* set to NULL so that switch_core_session_locate no longer succeeds, but don't lose the UUID in uuid_str so we
* can fire events with session UUID */
tech_pvt->sofia_private->uuid = NULL;
}
switch_mutex_unlock(tech_pvt->sofia_mutex);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sofia_on_exchange_media(switch_core_session_t *session)
{
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SOFIA EXCHANGE_MEDIA\n");
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sofia_on_soft_execute(switch_core_session_t *session)
{
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SOFIA SOFT_EXECUTE\n");
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sofia_acknowledge_call(switch_core_session_t *session)
{
struct private_object *tech_pvt = switch_core_session_get_private(session);
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
if (!tech_pvt->sent_100) {
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
nua_respond(tech_pvt->nh, SIP_100_TRYING, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
tech_pvt->sent_100 = 1;
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
static switch_status_t sofia_answer_channel(switch_core_session_t *session)
{
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status;
uint32_t session_timeout = tech_pvt->profile->session_timeout;
const char *val;
const char *b_sdp = NULL;
int is_proxy = 0;
int is_3pcc_proxy = 0;
2011-06-15 15:29:07 +00:00
int is_3pcc = 0;
char *sticky = NULL;
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
if(sofia_acknowledge_call(session) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Dialplan did not acknowledge_call; sent 100 Trying");
}
if (switch_channel_test_flag(channel, CF_CONFERENCE) && !zstr(tech_pvt->reply_contact) && !switch_stristr(";isfocus", tech_pvt->reply_contact)) {
2012-07-11 20:15:43 +00:00
tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;isfocus", tech_pvt->reply_contact);
}
2012-12-22 00:06:09 +00:00
//switch_core_media_set_local_sdp
2011-06-15 15:29:07 +00:00
if(sofia_test_flag(tech_pvt, TFLAG_3PCC_INVITE)) {
// SNARK: complete hack to get final ack sent when a 3pcc invite has been passed from the other leg in bypass_media mode.
// This code handles the pass_indication sent after the 3pcc ack is received by the other leg in the is_3pcc && is_proxy case below.
2011-06-15 15:29:07 +00:00
// Is there a better place to hang this...?
b_sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE);
2012-12-22 00:06:09 +00:00
switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
2011-06-15 15:29:07 +00:00
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
sofia_media_activate_rtp(tech_pvt);
switch_core_media_patch_sdp(tech_pvt->session);
switch_core_media_proxy_remote_addr(tech_pvt->session, NULL);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"3PCC-PROXY nomedia - sending ack, SDP:\n%s\n", tech_pvt->mparams.local_sdp_str);
if (sofia_use_soa(tech_pvt)) {
nua_ack(tech_pvt->nh,
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
SOATAG_REUSE_REJECTED(1),
SOATAG_RTP_SELECT(1),
SOATAG_AUDIO_AUX("cn telephone-event"),
TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
} else {
nua_ack(tech_pvt->nh,
NUTAG_MEDIA_ENABLE(0),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
TAG_IF(tech_pvt->mparams.local_sdp_str, SIPTAG_CONTENT_TYPE_STR("application/sdp")),
TAG_IF(tech_pvt->mparams.local_sdp_str, SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
SOATAG_AUDIO_AUX("cn telephone-event"),
TAG_END());
}
2011-06-15 15:29:07 +00:00
sofia_clear_flag(tech_pvt, TFLAG_3PCC_INVITE); // all done
2013-03-07 14:44:32 +00:00
sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
sofia_set_flag_locked(tech_pvt, TFLAG_SDP);
switch_channel_mark_answered(channel); // ... and remember to actually answer the call!
2011-06-15 15:29:07 +00:00
return SWITCH_STATUS_SUCCESS;
}
if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
b_sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE);
is_proxy = (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA));
is_3pcc_proxy = (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC));
is_3pcc = (!sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC));
if (b_sdp && is_proxy && !is_3pcc_proxy) {
2012-12-22 00:06:09 +00:00
switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
2012-12-22 00:06:09 +00:00
switch_core_media_patch_sdp(tech_pvt->session);
2012-12-18 22:06:29 +00:00
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
}
} else {
/* This if statement check and handles the 3pcc proxy mode */
2011-06-15 15:29:07 +00:00
if (is_3pcc) {
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
tech_pvt->mparams.local_sdp_str = NULL;
switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
} else if (is_3pcc_proxy) {
if (!(sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY))) {
switch_channel_set_flag(channel, CF_3PCC);
}
if (b_sdp && is_proxy && !switch_channel_var_true(channel, "3pcc_always_gen_sdp")) {
switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
} else {
switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
switch_core_media_prepare_codecs(session, 1);
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1);
sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
}
2011-06-15 15:29:07 +00:00
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_core_media_patch_sdp(tech_pvt->session);
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
2011-06-15 15:29:07 +00:00
}
}
}
if (is_3pcc || is_3pcc_proxy) {
/* Send the 200 OK */
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
if (sofia_use_soa(tech_pvt)) {
2013-11-07 22:48:00 +00:00
nua_respond(tech_pvt->nh, SIP_200_OK,
2011-06-16 17:01:34 +00:00
TAG_IF(is_proxy, NUTAG_AUTOANSWER(0)),
SIPTAG_CONTACT_STR(tech_pvt->profile->url),
2012-12-22 00:06:09 +00:00
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
SOATAG_REUSE_REJECTED(1),
2013-11-07 22:48:00 +00:00
SOATAG_RTP_SELECT(1),
2014-10-28 18:38:06 +00:00
SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)), TAG_END());
} else {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_MEDIA_ENABLE(0),
SIPTAG_CONTACT_STR(tech_pvt->profile->url),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
2012-12-22 00:06:09 +00:00
SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)), TAG_END());
}
switch_safe_free(extra_headers);
}
if (is_3pcc_proxy) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Sent a 200 OK, waiting for ACK\n");
/* Unlock the session signal to allow the ack to make it in */
// Maybe we should timeout?
switch_mutex_unlock(tech_pvt->sofia_mutex);
while (switch_channel_ready(channel) && !sofia_test_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)) {
switch_cond_next();
}
/* Regain lock on sofia */
switch_mutex_lock(tech_pvt->sofia_mutex);
if (is_proxy) {
sofia_clear_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
sofia_clear_flag(tech_pvt, TFLAG_3PCC);
switch_core_session_pass_indication(session, SWITCH_MESSAGE_INDICATE_ANSWER);
}
2011-06-15 15:29:07 +00:00
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n");
return SWITCH_STATUS_SUCCESS;
}
}
2012-12-22 00:06:09 +00:00
if ((is_proxy && !b_sdp) || sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) ||
switch_core_media_codec_chosen(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO) != SWITCH_STATUS_SUCCESS) {
sofia_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION);
if (is_proxy) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Disabling proxy mode due to call answer with no bridge\n");
switch_channel_clear_flag(channel, CF_PROXY_MEDIA);
switch_channel_clear_flag(channel, CF_PROXY_MODE);
}
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
2012-12-22 00:06:09 +00:00
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
if (zstr(r_sdp) || sofia_media_tech_media(tech_pvt, r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
//switch_mutex_lock(tech_pvt->sofia_mutex);
//nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
//switch_mutex_unlock(tech_pvt->sofia_mutex);
return SWITCH_STATUS_FALSE;
}
}
}
2012-12-22 00:06:09 +00:00
if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return status;
}
2013-11-07 22:48:00 +00:00
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
2012-12-18 22:06:29 +00:00
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
if (tech_pvt->nh) {
2012-12-22 00:06:09 +00:00
if (tech_pvt->mparams.local_sdp_str) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Local SDP %s:\n%s\n", switch_channel_get_name(channel),
2012-12-22 00:06:09 +00:00
tech_pvt->mparams.local_sdp_str);
}
}
2013-01-14 02:12:23 +00:00
}
if (sofia_test_flag(tech_pvt, TFLAG_NAT) ||
(val = switch_channel_get_variable(channel, "sip-force-contact")) ||
((val = switch_channel_get_variable(channel, "sip_sticky_contact")) && switch_true(val))) {
sticky = tech_pvt->record_route;
session_timeout = SOFIA_NAT_SESSION_TIMEOUT;
switch_channel_set_variable(channel, "sip_nat_detected", "true");
}
if ((val = switch_channel_get_variable(channel, SOFIA_SESSION_TIMEOUT))) {
int v_session_timeout = atoi(val);
if (v_session_timeout >= 0) {
session_timeout = v_session_timeout;
}
}
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
2010-04-20 18:34:51 +00:00
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
char *cid = NULL;
2010-10-06 13:38:32 +00:00
cid = generate_pai_str(tech_pvt);
2010-06-18 20:42:14 +00:00
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) && tech_pvt->mparams.early_sdp && tech_pvt->mparams.local_sdp_str) {
char *a, *b;
/* start at the s= line to avoid some devices who update the o= between messages */
2012-12-22 00:06:09 +00:00
a = strstr(tech_pvt->mparams.early_sdp, "s=");
b = strstr(tech_pvt->mparams.local_sdp_str, "s=");
if (!a || !b || strcmp(a, b)) {
/* The SIP RFC for SOA forbids sending a 183 with one sdp then a 200 with another but it won't do us much good unless
we do so in this case we will abandon the SOA rules and go rogue.
*/
sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
}
2010-06-18 20:42:14 +00:00
}
if ((tech_pvt->mparams.last_sdp_str && strstr(tech_pvt->mparams.last_sdp_str, "a=setup")) ||
2015-10-22 20:37:21 +00:00
(tech_pvt->mparams.local_sdp_str && strstr(tech_pvt->mparams.local_sdp_str, "a=setup"))) {
session_timeout = 0;
}
if ((tech_pvt->session_timeout = session_timeout)) {
tech_pvt->session_refresher = switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? nua_local_refresher : nua_remote_refresher;
if (sofia_test_pflag(tech_pvt->profile, PFLAG_UPDATE_REFRESHER) || switch_channel_var_true(tech_pvt->channel, "sip_update_refresher")) {
tech_pvt->update_refresher = 1;
}
} else {
tech_pvt->session_refresher = nua_no_refresher;
}
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_AUTOANSWER(0),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
NUTAG_SESSION_TIMER(tech_pvt->session_timeout),
NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher),
NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
2012-12-22 00:06:09 +00:00
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
2014-10-28 18:38:06 +00:00
SOATAG_REUSE_REJECTED(1),
SOATAG_AUDIO_AUX("cn telephone-event"),
2011-12-19 11:53:48 +00:00
TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
2013-11-07 22:48:00 +00:00
SOATAG_RTP_SELECT(1),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)), TAG_END());
} else {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_AUTOANSWER(0),
NUTAG_MEDIA_ENABLE(0),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
NUTAG_SESSION_TIMER(tech_pvt->session_timeout),
NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher),
NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
2012-12-22 00:06:09 +00:00
SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)), TAG_END());
}
switch_safe_free(extra_headers);
sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
}
return SWITCH_STATUS_SUCCESS;
}
2016-07-11 03:25:14 +00:00
static switch_status_t sofia_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
{
2016-10-12 23:00:13 +00:00
switch_status_t status;
if (switch_channel_test_flag(switch_core_session_get_channel(session), CF_MSRP)) {
switch_msrp_session_t *msrp_session = switch_core_media_get_msrp_session(session);
switch_frame_t *rframe = &msrp_session->frame;
switch_msrp_msg_t *msrp_msg = switch_msrp_session_pop_msg(msrp_session);
const char *msrp_h_content_type = NULL;
2016-10-12 23:00:13 +00:00
if (msrp_msg) {
msrp_h_content_type = switch_msrp_msg_get_header(msrp_msg, MSRP_H_CONTENT_TYPE);
2016-10-12 23:00:13 +00:00
}
rframe->flags = 0;
2016-10-12 23:00:13 +00:00
rframe->data = msrp_session->frame_data;
rframe->buflen = sizeof(msrp_session->frame_data);
2017-01-02 02:24:53 +00:00
if (msrp_msg && msrp_msg->method == MSRP_METHOD_SEND &&
msrp_msg->payload &&
2017-01-02 02:24:53 +00:00
!switch_stristr("?OTRv3?", msrp_msg->payload) &&
!switch_stristr("application/im-iscomposing", msrp_msg->payload) &&
msrp_h_content_type &&
(switch_stristr("text/plain", msrp_h_content_type) ||
switch_stristr("text/html", msrp_h_content_type) ||
switch_stristr("message/cpim", msrp_h_content_type))) {
2016-10-12 23:00:13 +00:00
rframe->datalen = msrp_msg->payload_bytes;
rframe->packetlen = msrp_msg->payload_bytes + 12;
memcpy(rframe->data, msrp_msg->payload, msrp_msg->payload_bytes + 1); /* include the last NULL byte */
2016-10-12 23:00:13 +00:00
rframe->m = 1;
*frame = rframe;
if (!strcasecmp(msrp_h_content_type, "message/cpim")) {
2016-10-12 23:00:13 +00:00
char *stripped_text = switch_html_strip((char *)rframe->data);
memcpy(rframe->data, stripped_text, strlen(stripped_text)+1);
rframe->datalen = strlen(stripped_text);
2016-10-12 23:00:13 +00:00
free(stripped_text);
}
switch_msrp_msg_destroy(&msrp_msg);
2016-10-12 23:00:13 +00:00
status = SWITCH_STATUS_SUCCESS;
} else {
rframe->datalen = 2;
rframe->flags = SFF_CNG;
*frame = rframe;
status = SWITCH_STATUS_SUCCESS;
}
return status;
}
2016-07-11 03:25:14 +00:00
return switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_TEXT);
}
static switch_status_t sofia_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
{
2016-07-18 16:48:43 +00:00
if (switch_channel_test_flag(switch_core_session_get_channel(session), CF_MSRP)) {
switch_msrp_session_t *msrp_session = switch_core_media_get_msrp_session(session);
if (frame && msrp_session) {
switch_msrp_msg_t *msrp_msg = switch_msrp_msg_create();
switch_status_t status = SWITCH_STATUS_SUCCESS;
// switch_msrp_msg_add_header(&msrp_msg, MSRP_H_CONTENT_TYPE, "message/cpim");
switch_msrp_msg_add_header(msrp_msg, MSRP_H_CONTENT_TYPE, "text/plain");
switch_msrp_msg_set_payload(msrp_msg, frame->data, frame->datalen);
status = switch_msrp_send(msrp_session, msrp_msg);
switch_msrp_msg_destroy(&msrp_msg);
return status;
2016-07-18 16:48:43 +00:00
}
return SWITCH_STATUS_FALSE;
}
2016-07-11 03:25:14 +00:00
return switch_core_media_write_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_TEXT);
}
static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
{
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
switch_assert(tech_pvt != NULL);
Media Management (Sponsored By Front Logic) This modification makes it possible to change the media path of session in the switch on-the-fly and from the dialplan. It adds some API interface calls usable from a remote client such as mod_event_socket or the test console. 1) media [off] <uuid> Turns on/off the media on the call described by <uuid> The media will be redirected as desiered either into the switch or point to point. 2) hold [off] <uuid> Turns on/off endpoint specific hold state on the session described by <uuid> 3) broadcast <uuid> "<path>[ <timer_name>]" or "speak:<tts_engine>|<tts_voice>|<text>[|<timer_name>]" [both] A message will be sent to the call described by uuid instructing it to play the file or speak the text indicated. If the 'both' option is specified both ends of the call will hear the message otherwise just the uuid specified will hear the message. During playback when only one side is hearing the message the other end will hear silence. If media is not flowing across the switch when the message is broadcasted, the media will be directed to the switch for the duration of the call and then returned to it's previous state. Also the no_media=true option in the dialplan before a bridge makes it possible to place a call while proxying the session description from one endpoint to the other and establishing an immidiate point-to-point media connection with no media on the switch. <action application="set" data="no_media=true"/> <action application="bridge" data="sofia/mydomain.com/myid@myhost.com"/> *NOTE* when connecting two outbound legs by using the "originate" api command with an extension that has no_media=true enabled, the media for the first leg will be engaged with the switch until the second leg has answered and the other session description is available to establish a point to point connection at which time point-to-point mode will be enabled. *NOTE* it is reccommended you rebuild FreeSWITCH with "make sure" as there have been some changes to the core. git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3245 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-10-31 21:38:06 +00:00
if (sofia_test_flag(tech_pvt, TFLAG_HUP)) {
return SWITCH_STATUS_FALSE;
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
}
2012-12-21 20:22:25 +00:00
#if 0
2012-12-22 00:06:09 +00:00
while (!(tech_pvt->video_read_codec.implementation && switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO) && !switch_channel_test_flag(channel, CF_REQ_MEDIA))) {
switch_ivr_parse_all_messages(tech_pvt->session);
if (--sanity && switch_channel_ready(channel)) {
switch_yield(10000);
} else {
switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE);
return SWITCH_STATUS_GENERR;
}
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
}
2012-12-21 20:22:25 +00:00
#endif
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
2012-12-21 20:22:25 +00:00
return switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_VIDEO);
}
static switch_status_t sofia_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
{
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
switch_assert(tech_pvt != NULL);
2012-12-21 20:22:25 +00:00
#if 0
2012-12-22 00:06:09 +00:00
while (!(tech_pvt->video_read_codec.implementation && switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO))) {
if (switch_channel_ready(channel)) {
switch_yield(10000);
} else {
return SWITCH_STATUS_GENERR;
}
}
2012-12-21 20:22:25 +00:00
#endif
if (sofia_test_flag(tech_pvt, TFLAG_HUP)) {
return SWITCH_STATUS_FALSE;
}
if (!sofia_test_flag(tech_pvt, TFLAG_RTP)) {
return SWITCH_STATUS_GENERR;
}
if (!sofia_test_flag(tech_pvt, TFLAG_IO)) {
return SWITCH_STATUS_SUCCESS;
}
2013-04-27 13:19:18 +00:00
if (SWITCH_STATUS_SUCCESS == switch_core_media_write_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_VIDEO)) {
2012-12-22 00:06:09 +00:00
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
{
private_object_t *tech_pvt = switch_core_session_get_private(session);
2012-12-22 00:06:09 +00:00
switch_status_t status = SWITCH_STATUS_FALSE;
switch_assert(tech_pvt != NULL);
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_RUNNING)) {
switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_NORMAL_CLEARING);
return SWITCH_STATUS_FALSE;
}
if (sofia_test_flag(tech_pvt, TFLAG_HUP)) {
return SWITCH_STATUS_FALSE;
}
if (!(switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO))){
return SWITCH_STATUS_INUSE;
}
sofia_set_flag_locked(tech_pvt, TFLAG_READING);
2012-12-22 00:06:09 +00:00
if (sofia_test_flag(tech_pvt, TFLAG_HUP) || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
return SWITCH_STATUS_FALSE;
}
2012-12-22 00:06:09 +00:00
status = switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_AUDIO);
sofia_clear_flag_locked(tech_pvt, TFLAG_READING);
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
2012-12-22 00:06:09 +00:00
return status;
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
}
static switch_status_t sofia_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
{
private_object_t *tech_pvt = switch_core_session_get_private(session);
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status = SWITCH_STATUS_SUCCESS;
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
switch_assert(tech_pvt != NULL);
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
if (!switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
if (switch_channel_up_nosig(channel)) {
return SWITCH_STATUS_SUCCESS;
} else {
return SWITCH_STATUS_GENERR;
}
}
if (switch_channel_test_flag(channel, CF_REQ_MEDIA)) {
if (++tech_pvt->req_media_counter > 2000) {
switch_channel_clear_flag(channel, CF_REQ_MEDIA);
switch_channel_hangup(channel, SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE);
return SWITCH_STATUS_FALSE;
} else {
return SWITCH_STATUS_SUCCESS;
}
} else {
tech_pvt->req_media_counter = 0;
}
if (sofia_test_flag(tech_pvt, TFLAG_HUP)) {
return SWITCH_STATUS_FALSE;
}
2012-12-22 00:06:09 +00:00
#if 0
if (!sofia_test_flag(tech_pvt, TFLAG_RTP)) {
return SWITCH_STATUS_GENERR;
}
if (!sofia_test_flag(tech_pvt, TFLAG_IO)) {
return SWITCH_STATUS_SUCCESS;
}
2012-12-22 00:06:09 +00:00
#endif
2012-12-22 00:06:09 +00:00
if (sofia_test_flag(tech_pvt, TFLAG_BYE)) {
return SWITCH_STATUS_FALSE;
}
sofia_set_flag_locked(tech_pvt, TFLAG_WRITING);
2012-12-22 00:06:09 +00:00
if (switch_core_media_write_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_AUDIO)) {
status = SWITCH_STATUS_SUCCESS;
}
sofia_clear_flag_locked(tech_pvt, TFLAG_WRITING);
return status;
}
static switch_status_t sofia_kill_channel(switch_core_session_t *session, int sig)
{
private_object_t *tech_pvt = switch_core_session_get_private(session);
if (!tech_pvt) {
return SWITCH_STATUS_FALSE;
}
switch (sig) {
case SWITCH_SIG_BREAK:
2012-12-22 00:06:09 +00:00
if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
switch_core_media_break(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
}
2012-12-22 00:06:09 +00:00
if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO)) {
switch_core_media_break(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO);
}
break;
case SWITCH_SIG_KILL:
default:
sofia_clear_flag_locked(tech_pvt, TFLAG_IO);
sofia_set_flag_locked(tech_pvt, TFLAG_HUP);
2012-12-22 00:06:09 +00:00
if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
switch_core_media_kill_socket(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
}
2012-12-22 00:06:09 +00:00
if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO)) {
switch_core_media_kill_socket(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO);
}
break;
}
return SWITCH_STATUS_SUCCESS;
}
2010-06-17 15:23:37 +00:00
static switch_status_t sofia_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
{
private_object_t *tech_pvt;
char message[128] = "";
2012-12-21 04:57:47 +00:00
switch_core_media_dtmf_t dtmf_type;
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
switch_assert(tech_pvt != NULL);
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
switch_core_media_check_dtmf_type(session);
2012-12-22 00:06:09 +00:00
dtmf_type = tech_pvt->mparams.dtmf_type;
/* We only can send INFO when we have no media */
if (!switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO) ||
2012-12-22 00:06:09 +00:00
!switch_channel_media_ready(tech_pvt->channel) || switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
dtmf_type = DTMF_INFO;
}
switch (dtmf_type) {
case DTMF_2833:
{
2012-12-22 00:06:09 +00:00
return switch_core_media_queue_rfc2833(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, dtmf);
}
case DTMF_INFO:
{
if (dtmf->digit == 'w') {
switch_yield(500000);
} else if (dtmf->digit == 'W') {
switch_yield(1000000);
} else {
snprintf(message, sizeof(message), "Signal=%c\r\nDuration=%d\r\n", dtmf->digit, dtmf->duration / 8);
switch_mutex_lock(tech_pvt->sofia_mutex);
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("application/dtmf-relay"), SIPTAG_PAYLOAD_STR(message), TAG_END());
switch_mutex_unlock(tech_pvt->sofia_mutex);
}
}
break;
case DTMF_NONE:
break;
default:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Unhandled DTMF type!\n");
break;
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sofia_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
{
switch_channel_t *channel = switch_core_session_get_channel(session);
private_object_t *tech_pvt = switch_core_session_get_private(session);
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_assert(tech_pvt != NULL);
if (msg->message_id == SWITCH_MESSAGE_INDICATE_SIGNAL_DATA) {
sofia_dispatch_event_t *de = (sofia_dispatch_event_t *) msg->pointer_arg;
switch_mutex_lock(tech_pvt->sofia_mutex);
if (switch_core_session_in_thread(session)) {
de->session = session;
}
2012-11-29 05:12:35 +00:00
2012-12-06 17:11:02 +00:00
sofia_process_dispatch_event(&de);
2012-11-29 05:12:35 +00:00
switch_mutex_unlock(tech_pvt->sofia_mutex);
goto end;
}
if (switch_channel_down(channel) || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
status = SWITCH_STATUS_FALSE;
goto end;
}
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
if (switch_channel_test_flag(channel, CF_CONFERENCE) && !zstr(tech_pvt->reply_contact) && !switch_stristr(";isfocus", tech_pvt->reply_contact)) {
tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;isfocus", tech_pvt->reply_contact);
}
/* ones that do not need to lock sofia mutex */
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_KEEPALIVE:
{
if (msg->numeric_arg) {
sofia_set_flag_locked(tech_pvt, TFLAG_KEEPALIVE);
} else {
sofia_clear_flag_locked(tech_pvt, TFLAG_KEEPALIVE);
}
}
break;
case SWITCH_MESSAGE_HEARTBEAT_EVENT:
{
char pl[160] = "";
switch_snprintf(pl, sizeof(pl), "KEEP-ALIVE %d\n", ++tech_pvt->keepalive);
if (sofia_test_flag(tech_pvt, TFLAG_KEEPALIVE)) {
if (tech_pvt->profile->keepalive == KA_MESSAGE) {
nua_message(tech_pvt->nh,
SIPTAG_CONTENT_TYPE_STR("text/plain"),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
SIPTAG_PAYLOAD_STR(pl),
TAG_END());
} else if (tech_pvt->profile->keepalive == KA_INFO) {
nua_info(tech_pvt->nh,
SIPTAG_CONTENT_TYPE_STR("text/plain"),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
SIPTAG_PAYLOAD_STR(pl),
TAG_END());
}
}
}
break;
case SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH:
case SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC:
break;
2012-12-22 00:06:09 +00:00
case SWITCH_MESSAGE_INDICATE_MEDIA_RENEG:
{
2012-12-22 00:06:09 +00:00
if (msg->string_arg) {
sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
}
2012-12-22 00:06:09 +00:00
sofia_glue_do_invite(session);
2010-12-10 23:47:24 +00:00
}
break;
case SWITCH_MESSAGE_INDICATE_BRIDGE:
switch_channel_set_variable(channel, SOFIA_REPLACES_HEADER, NULL);
2012-12-22 00:06:09 +00:00
if (switch_true(switch_channel_get_variable(channel, "sip_auto_simplify"))) {
2012-11-30 00:34:27 +00:00
sofia_set_flag(tech_pvt, TFLAG_SIMPLIFY);
}
2011-07-16 07:33:39 +00:00
2012-12-22 00:06:09 +00:00
break;
case SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE:
{
const char *event;
const char *uuid;
char *xdest;
if (msg->string_arg) {
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
NUTAG_SUBSTATE(nua_substate_terminated),
SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
SIPTAG_PAYLOAD_STR(msg->string_arg),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
SIPTAG_EVENT_STR("refer"), TAG_END());
goto end;
}
event = switch_channel_get_variable(channel, "sip_blind_transfer_event");
uuid = switch_channel_get_variable(channel, "blind_transfer_uuid");
if (event && uuid) {
char payload_str[255] = "SIP/2.0 403 Forbidden\r\n";
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
if (msg->numeric_arg) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s Completing blind transfer with success\n", switch_channel_get_name(channel));
switch_set_string(payload_str, "SIP/2.0 200 OK\r\n");
} else if (uuid) {
switch_core_session_t *other_session = switch_core_session_locate(uuid);
if (other_session) {
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
const char *invite_failure_status = switch_channel_get_variable(other_channel, "sip_invite_failure_status");
const char *invite_failure_str = switch_channel_get_variable(other_channel, "sip_invite_failure_status");
if (!zstr(invite_failure_status) && !zstr(invite_failure_str)) {
snprintf(payload_str, sizeof(payload_str), "SIP/2.0 %s %s\r\n", invite_failure_status, invite_failure_str);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s Completing blind transfer with custom failure: %s %s\n",
switch_channel_get_name(channel), invite_failure_status, invite_failure_str);
}
switch_core_session_rwunlock(other_session);
}
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s Completing blind transfer with status: %s\n", switch_channel_get_name(channel), payload_str);
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
NUTAG_SUBSTATE(nua_substate_terminated),
SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
SIPTAG_PAYLOAD_STR(payload_str),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
SIPTAG_EVENT_STR(event), TAG_END());
if (!msg->numeric_arg) {
xdest = switch_core_session_sprintf(session, "intercept:%s", uuid);
switch_ivr_session_transfer(session, xdest, "inline", NULL);
}
}
}
goto end;
2010-06-18 21:52:39 +00:00
case SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS:
if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
sofia_clear_flag(tech_pvt, TFLAG_EARLY_MEDIA);
}
goto end;
case SWITCH_MESSAGE_INDICATE_ANSWER:
case SWITCH_MESSAGE_INDICATE_PROGRESS:
{
const char *var;
const char *presence_data = switch_channel_get_variable(channel, "presence_data");
const char *presence_id = switch_channel_get_variable(channel, "presence_id");
if ((var = switch_channel_get_variable(channel, "sip_force_nat_mode")) && switch_true(var)) {
sofia_set_flag(tech_pvt, TFLAG_NAT);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setting NAT mode based on manual variable\n");
switch_channel_set_variable(channel, "sip_nat_detected", "true");
}
if ((var = switch_channel_get_variable(channel, "sip_enable_soa"))) {
if (switch_true(var)) {
sofia_set_flag(tech_pvt, TFLAG_ENABLE_SOA);
} else {
sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
}
}
if (presence_id || presence_data) {
char *sql = switch_mprintf("update sip_dialogs set presence_id='%q',presence_data='%q' "
2016-11-11 17:27:35 +00:00
"where uuid='%q';\n", switch_str_nil(presence_id), switch_str_nil(presence_data),
switch_core_session_get_uuid(session));
switch_assert(sql);
sofia_glue_execute_sql_now(tech_pvt->profile, &sql, SWITCH_TRUE);
}
2013-11-07 22:48:00 +00:00
if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) {
2013-07-29 15:18:05 +00:00
switch_core_media_reset_autofix(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
}
}
break;
default:
break;
}
/* ones that do need to lock sofia mutex */
switch_mutex_lock(tech_pvt->sofia_mutex);
if (switch_channel_down(channel) || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
status = SWITCH_STATUS_FALSE;
goto end_lock;
}
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_DEFLECT: {
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_HEADER_PREFIX);
char ref_to[1024] = "";
const char *var;
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
if (!strcasecmp(msg->string_arg, "sip:")) {
const char *format = strchr(tech_pvt->profile->sipip, ':') ? "sip:%s@[%s]" : "sip:%s@%s";
switch_snprintf(ref_to, sizeof(ref_to), format, msg->string_arg, tech_pvt->profile->sipip);
} else {
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_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
if (msg->string_array_arg[0]) {
tech_pvt->proxy_refer_uuid = (char *)msg->string_array_arg[0];
} else {
switch_mutex_unlock(tech_pvt->sofia_mutex);
sofia_wait_for_reply(tech_pvt, 9999, 10);
switch_mutex_lock(tech_pvt->sofia_mutex);
if ((var = switch_channel_get_variable(tech_pvt->channel, "sip_refer_reply"))) {
msg->string_reply = switch_core_session_strdup(session, var);
} else {
msg->string_reply = "no reply";
}
switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_BLIND_TRANSFER);
}
switch_safe_free(extra_headers);
}
break;
case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ:
if (switch_channel_media_up(channel) && !switch_channel_test_flag(channel, CF_AVPF) && !switch_channel_test_flag(channel, CF_MANUAL_VID_REFRESH) &&
switch_channel_var_true(channel, "sofia_send_info_vid_refresh")) {
const char *pl = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<media_control><vc_primitive><to_encoder><picture_fast_update /></to_encoder></vc_primitive></media_control>\n";
switch_time_t now = switch_micro_time_now();
if (!tech_pvt->last_vid_info || (now - tech_pvt->last_vid_info) > 500000) {
tech_pvt->last_vid_info = now;
if (!zstr(msg->string_arg)) {
pl = msg->string_arg;
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("application/media_control+xml"), SIPTAG_PAYLOAD_STR(pl), TAG_END());
}
}
break;
case SWITCH_MESSAGE_INDICATE_BROADCAST:
{
const char *ip = NULL, *port = NULL;
ip = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE);
port = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE);
if (ip && port) {
2013-11-07 22:48:00 +00:00
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, ip, (switch_port_t)atoi(port), msg->string_arg, 1);
}
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
2012-12-22 00:06:09 +00:00
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
2014-10-28 18:38:06 +00:00
SOATAG_REUSE_REJECTED(1),
SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
} else {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_MEDIA_ENABLE(0),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
switch_channel_mark_answered(channel);
}
}
break;
case SWITCH_MESSAGE_INDICATE_NOMEDIA:
{
sofia_glue_do_invite(session);
}
break;
case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT:
{
if (zstr(msg->string_arg)) { /* no sdp requires proxy of ack */
switch_core_session_t *other_session;
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
if (switch_core_session_compare(session, other_session)) {
private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
sofia_set_flag(other_tech_pvt, TFLAG_PASS_ACK);
}
switch_core_session_rwunlock(other_session);
}
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Sending media re-direct:\n%s\n",
switch_channel_get_name(channel), switch_str_nil(msg->string_arg));
2012-12-22 00:06:09 +00:00
switch_core_media_set_local_sdp(session, msg->string_arg, SWITCH_TRUE);
if (zstr(tech_pvt->mparams.local_sdp_str)) {
2013-01-07 16:27:28 +00:00
sofia_set_flag(tech_pvt, TFLAG_3PCC_INVITE);
}
2013-01-07 16:27:28 +00:00
sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
2013-01-07 16:27:28 +00:00
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
}
2013-01-07 16:27:28 +00:00
sofia_glue_do_invite(session);
2012-12-22 00:06:09 +00:00
}
break;
2010-05-13 02:25:54 +00:00
case SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION:
{
2010-05-13 02:25:54 +00:00
switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
2010-06-23 18:22:52 +00:00
2010-05-13 02:25:54 +00:00
if (!t38_options) {
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
2010-05-13 02:25:54 +00:00
goto end_lock;
}
2012-12-22 00:06:09 +00:00
switch_core_media_start_udptl(tech_pvt->session, t38_options);
2010-05-13 02:25:54 +00:00
switch_core_media_set_udptl_image_sdp(tech_pvt->session, t38_options, msg->numeric_arg);
2010-06-23 18:22:52 +00:00
2010-05-13 02:25:54 +00:00
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_AUTOANSWER(0),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
2012-12-22 00:06:09 +00:00
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
2014-10-28 18:38:06 +00:00
SOATAG_REUSE_REJECTED(1),
SOATAG_ORDERED_USER(1),
2014-10-28 18:38:06 +00:00
SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
2010-05-13 02:25:54 +00:00
} else {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_AUTOANSWER(0),
NUTAG_MEDIA_ENABLE(0),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
2010-05-13 02:25:54 +00:00
}
switch_safe_free(extra_headers);
sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
2010-06-23 18:22:52 +00:00
}
2010-05-13 02:25:54 +00:00
}
break;
2010-05-13 02:25:54 +00:00
case SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA:
{
switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
2012-02-17 15:57:56 +00:00
if (t38_options) {
switch_core_media_set_udptl_image_sdp(tech_pvt->session, t38_options, msg->numeric_arg);
2010-06-23 18:22:52 +00:00
2012-02-17 15:57:56 +00:00
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
}
sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
sofia_glue_do_invite(session);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s Request to send IMAGE on channel with not t38 options.\n",
2012-02-17 15:57:56 +00:00
switch_channel_get_name(channel));
}
}
break;
case SWITCH_MESSAGE_INDICATE_3P_NOMEDIA:
{
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_HEADER_PREFIX);
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
switch_channel_clear_flag(tech_pvt->channel, CF_MEDIA_ACK);
switch_channel_set_flag(tech_pvt->channel, CF_REQ_MEDIA);
sofia_glue_clear_soa(session, SWITCH_TRUE);
nua_invite(tech_pvt->nh,
NUTAG_MEDIA_ENABLE(0),
TAG_IF(msg->string_arg, SIPTAG_CONTENT_TYPE_STR("application/sdp")),
SIPTAG_PAYLOAD_STR(msg->string_arg),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
switch_safe_free(extra_headers);
}
break;
case SWITCH_MESSAGE_INDICATE_3P_MEDIA:
{
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_HEADER_PREFIX);
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
switch_channel_clear_flag(tech_pvt->channel, CF_MEDIA_ACK);
switch_channel_clear_flag(tech_pvt->channel, CF_MEDIA_SET);
switch_channel_set_flag(tech_pvt->channel, CF_REQ_MEDIA);
sofia_glue_clear_soa(session, SWITCH_TRUE);
nua_invite(tech_pvt->nh, NUTAG_MEDIA_ENABLE(0), SIPTAG_PAYLOAD_STR(""),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
switch_safe_free(extra_headers);
}
break;
case SWITCH_MESSAGE_INDICATE_MEDIA:
{
uint32_t send_invite = 1;
2014-10-03 16:34:37 +00:00
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
switch_channel_clear_flag(channel, CF_PROXY_MODE);
2012-12-22 00:06:09 +00:00
switch_core_media_set_local_sdp(session, NULL, SWITCH_FALSE);
if (!(switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_test_flag(channel, CF_EARLY_MEDIA))) {
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
2012-12-22 00:06:09 +00:00
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
if (sofia_media_tech_media(tech_pvt, r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
status = SWITCH_STATUS_FALSE;
goto end_lock;
}
send_invite = 0;
}
}
2014-10-03 16:34:37 +00:00
2014-10-07 18:47:44 +00:00
switch_core_media_set_sdp_codec_string(tech_pvt->session, r_sdp, SDP_TYPE_RESPONSE);
switch_channel_set_variable(tech_pvt->channel, "absolute_codec_string", switch_channel_get_variable(tech_pvt->channel, "ep_codec_string"));
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
2014-10-07 18:47:44 +00:00
if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
goto end_lock;
}
2013-11-07 22:48:00 +00:00
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1);
if (!msg->numeric_arg) {
if (send_invite) {
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
}
sofia_glue_do_invite(session);
} else {
status = SWITCH_STATUS_FALSE;
}
}
}
break;
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
case SWITCH_MESSAGE_INDICATE_PHONE_EVENT:
2010-04-16 14:35:41 +00:00
{
const char *event = "talk";
const char *full_to = NULL;
if (!zstr(msg->string_arg) && strcasecmp(msg->string_arg, event)) {
if (!strcasecmp(msg->string_arg, "hold")) {
event = "hold";
} else if (strncasecmp(msg->string_arg, "talk", 4)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid event.\n");
}
}
if (!switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
"Operation not permitted on an inbound non-answered call leg!\n");
} else {
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
full_to = switch_str_nil(switch_channel_get_variable(channel, "sip_full_to"));
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active),
TAG_IF((full_to), SIPTAG_TO_STR(full_to)),SIPTAG_SUBSCRIPTION_STATE_STR("active"),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_EVENT_STR(event),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
2011-11-21 15:17:21 +00:00
2010-04-16 14:35:41 +00:00
}
2014-03-18 23:58:13 +00:00
break;
2012-08-31 20:35:13 +00:00
case SWITCH_MESSAGE_INDICATE_MESSAGE:
{
2015-09-23 16:58:57 +00:00
char ct[256] = "text/plain";
2012-08-31 20:35:13 +00:00
int ok = 0;
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
2012-08-31 20:35:13 +00:00
2012-09-08 06:28:35 +00:00
if (!zstr(msg->string_array_arg[3]) && !strcmp(msg->string_array_arg[3], tech_pvt->caller_profile->uuid)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Not sending message back to sender\n");
break;
}
2012-08-31 20:35:13 +00:00
if (switch_stristr("send_message", tech_pvt->x_freeswitch_support_remote)) {
ok = 1;
}
if (switch_true(switch_channel_get_variable(channel, "fs_send_unsupported_message"))) {
ok = 1;
}
if (ok) {
const char *pl = NULL;
2015-09-23 16:58:57 +00:00
if (!zstr(msg->string_array_arg[0]) && !zstr(msg->string_array_arg[1])) {
switch_snprintf(ct, sizeof(ct), "%s/%s", msg->string_array_arg[0], msg->string_array_arg[1]);
}
2012-08-31 20:35:13 +00:00
if (!zstr(msg->string_array_arg[2])) {
pl = msg->string_array_arg[2];
}
nua_message(tech_pvt->nh,
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_CONTENT_TYPE_STR(ct),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(pl, SIPTAG_PAYLOAD_STR(pl)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
2012-08-31 20:35:13 +00:00
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s send_message is not supported.\n", switch_channel_get_name(channel));
}
}
break;
case SWITCH_MESSAGE_INDICATE_INFO:
{
2015-09-23 16:58:57 +00:00
char ct[256] = "freeswitch/data";
int ok = 0;
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
if (switch_stristr("send_info", tech_pvt->x_freeswitch_support_remote)) {
ok = 1;
}
2015-09-23 16:58:57 +00:00
if (switch_true(switch_channel_get_variable_dup(channel, "fs_send_unsupported_info", SWITCH_FALSE, -1))) {
ok = 1;
}
if (ok) {
char *headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_INFO_HEADER_PREFIX);
const char *pl = NULL;
2014-11-12 19:07:43 +00:00
2015-09-23 16:58:57 +00:00
if (!zstr(msg->string_array_arg[0]) && !zstr(msg->string_array_arg[1])) {
switch_snprintf(ct, sizeof(ct), "%s/%s", msg->string_array_arg[0], msg->string_array_arg[1]);
}
if (!zstr(msg->string_array_arg[2])) {
pl = msg->string_array_arg[2];
}
2014-11-12 19:07:43 +00:00
nua_info(tech_pvt->nh,
SIPTAG_CONTENT_TYPE_STR(ct),
TAG_IF(!zstr(headers), SIPTAG_HEADER_STR(headers)),
2014-11-12 19:07:43 +00:00
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(pl, SIPTAG_PAYLOAD_STR(pl)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
2014-11-12 19:07:43 +00:00
switch_safe_free(headers);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s send_info is not supported.\n", switch_channel_get_name(channel));
}
2010-04-16 14:35:41 +00:00
}
break;
case SWITCH_MESSAGE_INDICATE_SIMPLIFY:
{
char *ref_to, *ref_by;
const char *uuid;
const char *call_id = NULL, *to_user = NULL, *to_host = NULL, *to_tag = NULL, *from_tag = NULL, *from_user = NULL, *from_host = NULL;
if ((uuid = switch_channel_get_partner_uuid(channel))) {
switch_core_session_t *rsession;
if ((rsession = switch_core_session_locate(uuid))) {
switch_channel_t *rchannel = switch_core_session_get_channel(rsession);
call_id = switch_channel_get_variable(rchannel, "sip_call_id");
to_user = switch_channel_get_variable(rchannel, "sip_to_user");
if (switch_channel_direction(rchannel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
to_host = switch_channel_get_variable(rchannel, "sip_to_host");
from_user = switch_channel_get_variable(channel, "sip_from_user");
from_host = switch_channel_get_variable(channel, "sip_from_host");
2010-08-17 14:41:21 +00:00
to_tag = switch_channel_get_variable(rchannel, "sip_to_tag");
from_tag = switch_channel_get_variable(rchannel, "sip_from_tag");
} else {
to_host = switch_channel_get_variable(channel, "sip_to_host");
from_user = switch_channel_get_variable(rchannel, "sip_from_user");
from_host = switch_channel_get_variable(rchannel, "sip_from_host");
2010-08-17 14:41:21 +00:00
from_tag = switch_channel_get_variable(rchannel, "sip_to_tag");
to_tag = switch_channel_get_variable(rchannel, "sip_from_tag");
}
switch_core_session_rwunlock(rsession);
}
}
if (to_user && to_host && from_user && from_host && call_id && to_tag && from_tag) {
char in[512] = "", out[1536] = "";
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
switch_snprintf(in, sizeof(in), "%s;to-tag=%s;from-tag=%s", call_id, to_tag, from_tag);
switch_url_encode(in, out, sizeof(out));
ref_to = switch_mprintf("<sip:%s@%s?Replaces=%s>", to_user, to_host, out);
ref_by = switch_mprintf("<sip:%s@%s>", from_user, from_host);
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
nua_refer(tech_pvt->nh, SIPTAG_REFER_TO_STR(ref_to), SIPTAG_REFERRED_BY_STR(ref_by),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
switch_safe_free(ref_to);
switch_safe_free(ref_by);
}
}
break;
case SWITCH_MESSAGE_INDICATE_DISPLAY:
{
2013-09-19 15:15:02 +00:00
const char *name = NULL, *number = NULL;
const char *call_info = NULL;
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SEND_DISPLAY_UPDATE)) {
goto end_lock;
}
name = msg->string_array_arg[0];
number = msg->string_array_arg[1];
call_info = switch_channel_get_variable(channel, "presence_call_info_full");
if (!zstr(name) && strcmp(name, "_undef_")) {
char message[256] = "";
const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent");
const char *allow = switch_channel_get_variable(tech_pvt->channel, "sip_allow");
switch_event_t *event;
int update_allowed = 0;
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
2011-10-06 03:54:31 +00:00
check_decode(name, tech_pvt->session);
if (allow) {
update_allowed = !!switch_stristr("UPDATE", allow);
}
2011-10-06 03:54:31 +00:00
if (zstr(number)) {
number = tech_pvt->caller_profile->destination_number;
}
switch_ivr_eavesdrop_update_display(session, name, number);
2012-02-03 17:50:24 +00:00
if (!sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY) && switch_channel_test_flag(channel, CF_ANSWERED)) {
if (zstr(tech_pvt->last_sent_callee_id_name) || strcmp(tech_pvt->last_sent_callee_id_name, name) ||
zstr(tech_pvt->last_sent_callee_id_number) || strcmp(tech_pvt->last_sent_callee_id_number, number)) {
if (switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote)) {
snprintf(message, sizeof(message), "X-FS-Display-Name: %s\nX-FS-Display-Number: %s\n", name, number);
if (switch_channel_test_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER)) {
snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Lazy-Attended-Transfer: true\n");
switch_channel_clear_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER);
switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
}
if (switch_channel_test_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER)) {
snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Attended-Transfer: true\n");
switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/update_display"),
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
} else if (ua && switch_stristr("snom", ua)) {
const char *ver_str = NULL;
2012-10-18 20:55:55 +00:00
int version = 0;
ver_str = switch_stristr( "/", ua);
if ( ver_str ) {
char *argv[4] = { 0 };
char *dotted = strdup( ver_str + 1 );
switch_assert(dotted);
switch_separate_string(dotted, '.', argv, (sizeof(argv) / sizeof(argv[0])));
if ( argv[0] && argv[1] && argv[2] ) {
version = ( atoi(argv[0]) * 10000 ) + ( atoi(argv[1]) * 100 ) + atoi(argv[2]);
2012-10-18 20:55:55 +00:00
}
switch_safe_free( dotted );
}
if ( version >= 80424 ) {
if (zstr(name)) {
snprintf(message, sizeof(message), "From: %s\r\nTo:\r\n", number);
} else {
snprintf(message, sizeof(message), "From: \"%s\" %s\r\nTo:\r\n", name, number);
}
} else {
if (zstr(name)) {
snprintf(message, sizeof(message), "From:\r\nTo: %s\r\n", number);
} else {
snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", name, number);
}
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), SIPTAG_PAYLOAD_STR(message), TAG_END());
} else if (update_allowed && ua && (switch_stristr("polycom", ua) ||
(switch_stristr("aastra", ua) && !switch_stristr("Intelligate", ua)) ||
(switch_stristr("cisco/spa50", ua) ||
switch_stristr("cisco/spa525", ua)) ||
switch_stristr("cisco/spa30", ua) ||
switch_stristr("Grandstream", ua) ||
switch_stristr("Yealink", ua) ||
switch_stristr("Mitel", ua) ||
switch_stristr("Panasonic", ua))) {
2016-11-10 19:42:26 +00:00
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <sip:%s@%s>", name, number, tech_pvt->profile->sipip);
sofia_set_flag_locked(tech_pvt, TFLAG_UPDATING_DISPLAY);
nua_update(tech_pvt->nh,
NUTAG_SESSION_TIMER(tech_pvt->session_timeout),
NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher),
NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher),
TAG_IF(!zstr(tech_pvt->privacy), SIPTAG_PRIVACY_STR(tech_pvt->privacy)),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri)),
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
tech_pvt->last_sent_callee_id_name = switch_core_session_strdup(tech_pvt->session, name);
tech_pvt->last_sent_callee_id_number = switch_core_session_strdup(tech_pvt->session, number);
2011-09-01 20:10:23 +00:00
if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) {
const char *uuid = switch_channel_get_partner_uuid(channel);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "SEND");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sent-Callee-ID-Name", name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sent-Callee-ID-Number", number);
//switch_channel_set_profile_var(channel, "callee_id_name", name);
//switch_channel_set_profile_var(channel, "callee_id_number", number);
if (uuid) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid);
}
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Not sending same id again \"%s\" <%s>\n", name, number);
}
}
}
}
break;
case SWITCH_MESSAGE_INDICATE_HOLD:
{
if (msg->numeric_arg) {
2012-12-21 20:22:25 +00:00
switch_core_media_toggle_hold(session, 1);
} else {
sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_set_flag(channel, CF_LEG_HOLDING);
sofia_glue_do_invite(session);
if (!zstr(msg->string_arg)) {
char message[256] = "";
const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent");
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
if (ua && switch_stristr("snom", ua)) {
snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", msg->string_arg, tech_pvt->caller_profile->destination_number);
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
SIPTAG_PAYLOAD_STR(message),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
} else if (ua && switch_stristr("polycom", ua)) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", msg->string_arg, tech_pvt->caller_profile->destination_number);
nua_update(tech_pvt->nh,
NUTAG_SESSION_TIMER(tech_pvt->session_timeout),
NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher),
NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher),
TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri)),
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
}
}
}
break;
case SWITCH_MESSAGE_INDICATE_UNHOLD:
{
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_clear_flag(channel, CF_LEG_HOLDING);
sofia_glue_do_invite(session);
}
break;
case SWITCH_MESSAGE_INDICATE_REDIRECT:
2012-06-27 17:25:03 +00:00
#define MAX_REDIR 128
if (!zstr(msg->string_arg)) {
2012-06-27 17:25:03 +00:00
if (!switch_channel_test_flag(channel, CF_ANSWERED) && !sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *mydest = (char *) msg->string_arg;
char *argv[MAX_REDIR] = { 0 };
2010-05-19 21:24:52 +00:00
char *mydata = NULL, *newdest = NULL;
2012-06-27 17:25:03 +00:00
int argc = 0, i;
2010-05-19 21:24:52 +00:00
switch_size_t len = 0;
switch_call_cause_t sip_redirect_cause = SWITCH_CAUSE_NORMAL_UNSPECIFIED;
char *dest = switch_core_session_strdup(session, mydest);
if ((argc = switch_separate_string(dest, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) {
const char *redirect_cause = argv[1];
sip_redirect_cause = switch_channel_str2cause(redirect_cause);
}
2010-05-19 21:24:52 +00:00
if (strchr(dest, ',')) {
mydata = dest;
2010-05-19 21:24:52 +00:00
len = strlen(mydata) * 2;
newdest = switch_core_session_alloc(session, len);
2010-06-23 18:22:52 +00:00
2010-05-19 21:24:52 +00:00
argc = switch_split(mydata, ',', argv);
2010-06-23 18:22:52 +00:00
for (i = 0; i < argc; i++) {
2010-05-19 21:24:52 +00:00
if (!strchr(argv[i], '<') && !strchr(argv[i], '>')) {
if (argc > 1) {
if (i == argc - 1) {
switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "\"unknown\" <%s>;q=%1.3f",
argv[i], (double)((double)(MAX_REDIR + 1 - i))/1000);
} else {
switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "\"unknown\" <%s>;q=%1.3f,",
argv[i], (double)((double)(MAX_REDIR + 1 - i))/1000);
}
2010-05-19 21:24:52 +00:00
} else {
if (i == argc - 1) {
switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "\"unknown\" <%s>", argv[i]);
} else {
switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "\"unknown\" <%s>,", argv[i]);
}
2010-05-19 21:24:52 +00:00
}
} else {
if (i == argc - 1) {
switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "%s", argv[i]);
} else {
switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "%s,", argv[i]);
}
}
}
2010-06-23 18:22:52 +00:00
2010-05-19 21:24:52 +00:00
dest = newdest;
} else {
2010-05-19 21:24:52 +00:00
if (!strchr(dest, '<') && !strchr(dest, '>')) {
dest = switch_core_session_sprintf(session, "\"unknown\" <%s>", dest);
}
}
2010-06-23 18:22:52 +00:00
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Redirecting to %s\n", dest);
2012-06-27 17:25:03 +00:00
tech_pvt->respond_dest = dest;
2010-05-19 21:24:52 +00:00
if (argc > 1) {
2012-06-27 17:25:03 +00:00
tech_pvt->respond_code = 300;
tech_pvt->respond_phrase = "Multiple Choices";
2010-05-19 21:24:52 +00:00
} else {
2012-06-27 17:25:03 +00:00
tech_pvt->respond_code = 302;
tech_pvt->respond_phrase = "Moved Temporarily";
2010-05-19 21:24:52 +00:00
}
if (sip_redirect_cause == SWITCH_CAUSE_NONE) {
sip_redirect_cause = SWITCH_CAUSE_NORMAL_UNSPECIFIED;
}
switch_channel_hangup(tech_pvt->channel, sip_redirect_cause);
2010-05-19 21:24:52 +00:00
} else {
2010-05-19 21:24:52 +00:00
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Too late for redirecting, already answered\n");
2010-06-23 18:22:52 +00:00
}
}
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
break;
case SWITCH_MESSAGE_INDICATE_RESPOND:
2012-06-11 16:13:19 +00:00
{
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
if (switch_channel_test_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE)) {
switch_channel_clear_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE);
switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
SOATAG_REUSE_REJECTED(1),
SOATAG_AUDIO_AUX("cn telephone-event"),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
} else {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_MEDIA_ENABLE(0),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
}
2012-06-11 16:13:19 +00:00
if (msg->numeric_arg || msg->string_arg) {
int code = msg->numeric_arg;
const char *reason = NULL;
if (code > 0) {
2012-06-11 16:13:19 +00:00
reason = msg->string_arg;
} else {
if (!zstr(msg->string_arg)) {
if ((code = atoi(msg->string_arg))) {
if ((reason = strchr(msg->string_arg, ' '))) {
reason++;
}
}
}
}
2012-06-11 16:13:19 +00:00
if (!code) {
code = 488;
}
2012-06-11 16:13:19 +00:00
if (!switch_channel_test_flag(channel, CF_ANSWERED) && code >= 300) {
if (sofia_test_flag(tech_pvt, TFLAG_BYE)) {
goto end_lock;
}
}
2012-06-11 16:13:19 +00:00
if (zstr(reason) && code != 407 && code != 302) {
reason = sip_status_phrase(code);
if (zstr(reason)) {
reason = "Because";
}
}
/* Dialplan should really use acknowledge_call application instead of respond application to send 100 */
if (code == 100) {
status = sofia_acknowledge_call(session);
goto end_lock;
}
if (tech_pvt->proxy_refer_uuid) {
if (tech_pvt->proxy_refer_msg) {
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_EXPIRES_STR("60"),
NUTAG_WITH_THIS_MSG(tech_pvt->proxy_refer_msg),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
msg_ref_destroy(tech_pvt->proxy_refer_msg);
tech_pvt->proxy_refer_msg = NULL;
}
goto end_lock;
}
2012-07-03 14:23:25 +00:00
if (code == 302 && !zstr(msg->string_arg)) {
2012-06-11 16:13:19 +00:00
char *p;
if ((p = strchr(msg->string_arg, ' '))) {
*p = '\0';
msg->string_arg = p;
}
msg->message_id = SWITCH_MESSAGE_INDICATE_REDIRECT;
switch_core_session_receive_message(session, msg);
goto end_lock;
} else {
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
char *sdp = (char *) msg->pointer_arg;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Responding with %d [%s]\n", code, reason);
sofia_clear_flag(tech_pvt, TFLAG_REINVITED);
if (!zstr((sdp))) {
if (!strcasecmp(sdp, "t38")) {
switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
if (t38_options) {
switch_core_media_set_udptl_image_sdp(tech_pvt->session, t38_options, 0);
2012-12-22 00:06:09 +00:00
if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
switch_channel_clear_flag(tech_pvt->channel, CF_NOTIMER_DURING_BRIDGE);
switch_core_media_udptl_mode(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
2012-06-11 16:13:19 +00:00
}
2010-09-27 17:44:36 +00:00
}
2012-06-11 16:13:19 +00:00
} else {
2012-12-22 00:06:09 +00:00
switch_core_media_set_local_sdp(session, sdp, SWITCH_TRUE);
2010-05-27 01:12:54 +00:00
}
2012-06-11 16:13:19 +00:00
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
2012-12-22 00:06:09 +00:00
switch_core_media_patch_sdp(tech_pvt->session);
switch_core_media_proxy_remote_addr(session, NULL);
2011-06-15 15:29:07 +00:00
}
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
SOATAG_REUSE_REJECTED(1),
SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
} else {
nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
NUTAG_MEDIA_ENABLE(0),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
2012-06-11 16:13:19 +00:00
if (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC)) {
/* Unlock the session signal to allow the ack to make it in */
// Maybe we should timeout?
switch_mutex_unlock(tech_pvt->sofia_mutex);
while (switch_channel_ready(channel) && !sofia_test_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)) {
switch_ivr_parse_all_events(session);
switch_yield(10000);
2012-06-11 16:13:19 +00:00
}
2011-06-15 15:29:07 +00:00
2012-06-11 16:13:19 +00:00
/* Regain lock on sofia */
switch_mutex_lock(tech_pvt->sofia_mutex);
2012-06-11 16:13:19 +00:00
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n");
sofia_clear_flag(tech_pvt, TFLAG_3PCC);
sofia_clear_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
switch_core_session_pass_indication(session, SWITCH_MESSAGE_INDICATE_ANSWER);
}
} else {
2012-09-21 19:45:30 +00:00
if (msg->numeric_arg && !(switch_channel_test_flag(channel, CF_ANSWERED) && code == 488)) {
if (code > 399) {
2012-07-03 14:23:25 +00:00
switch_call_cause_t cause = sofia_glue_sip_cause_to_freeswitch(code);
if (code == 401 || cause == 407) cause = SWITCH_CAUSE_USER_CHALLENGE;
tech_pvt->respond_code = code;
tech_pvt->respond_phrase = switch_core_session_strdup(tech_pvt->session, reason);
2012-07-03 14:23:25 +00:00
switch_channel_hangup(tech_pvt->channel, cause);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot respond.\n");
}
} else {
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
2011-06-15 15:29:07 +00:00
}
2012-06-11 16:13:19 +00:00
switch_safe_free(extra_headers);
}
}
2012-06-11 16:13:19 +00:00
}
}
break;
case SWITCH_MESSAGE_INDICATE_ALERTING:
{
char *extra_header = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
char *cid = generate_pai_str(tech_pvt);
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
nua_respond(tech_pvt->nh, SIP_180_RINGING,
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(!zstr(extra_header), SIPTAG_HEADER_STR(extra_header)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
break;
case SWITCH_MESSAGE_INDICATE_ACKNOWLEDGE_CALL:
status = sofia_acknowledge_call(session);
break;
case SWITCH_MESSAGE_INDICATE_RINGING:
2010-06-15 20:48:12 +00:00
{
switch_ring_ready_t ring_ready_val = msg->numeric_arg;
if(sofia_acknowledge_call(session) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Dialplan did not acknowledge_call; sent 100 Trying");
}
2010-06-15 20:48:12 +00:00
if (!switch_channel_test_flag(channel, CF_RING_READY) && !sofia_test_flag(tech_pvt, TFLAG_BYE) &&
!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
char *extra_header = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
2010-10-06 13:38:32 +00:00
char *cid = generate_pai_str(tech_pvt);
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
2010-06-23 18:22:52 +00:00
/* Set sip_to_tag to local tag for inbound channels. */
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
const char* to_tag = "";
to_tag = switch_str_nil(nta_leg_get_tag(tech_pvt->nh->nh_ds->ds_leg));
if(to_tag) {
switch_channel_set_variable(channel, "sip_to_tag", to_tag);
}
}
2010-06-15 20:48:12 +00:00
switch (ring_ready_val) {
case SWITCH_RING_READY_QUEUED:
nua_respond(tech_pvt->nh, SIP_182_QUEUED,
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
2010-06-15 20:48:12 +00:00
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(!zstr(extra_header), SIPTAG_HEADER_STR(extra_header)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
2010-06-15 20:48:12 +00:00
break;
case SWITCH_RING_READY_RINGING:
default:
nua_respond(tech_pvt->nh, SIP_180_RINGING,
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
2010-06-15 20:48:12 +00:00
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(!zstr(extra_header), SIPTAG_HEADER_STR(extra_header)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
2010-06-15 20:48:12 +00:00
break;
}
switch_safe_free(extra_header);
switch_channel_mark_ring_ready(channel);
}
}
break;
case SWITCH_MESSAGE_INDICATE_ANSWER:
status = sofia_answer_channel(session);
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
break;
case SWITCH_MESSAGE_INDICATE_PROGRESS:
{
char *sticky = NULL;
const char *val = NULL;
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
const char *b_sdp = NULL;
int is_proxy = 0, is_3pcc_proxy = 0;
int send_sip_code = 183;
const char * p_send_sip_msg = sip_183_Session_progress;
if(sofia_acknowledge_call(session) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Dialplan did not acknowledge_call; sent 100 Trying");
}
b_sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE);
is_proxy = (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA));
is_3pcc_proxy = (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC));
// send 180 instead of 183 if variable "early_use_180" is "true"
if (switch_true(switch_channel_get_variable(channel, "early_use_180"))) {
send_sip_code = 180;
p_send_sip_msg = sip_180_Ringing;
}
if (b_sdp && is_proxy && !is_3pcc_proxy) {
switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_core_media_patch_sdp(tech_pvt->session);
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
2014-03-19 20:38:53 +00:00
status = SWITCH_STATUS_FALSE;
goto end_lock;
}
}
}
if (!sofia_test_flag(tech_pvt, TFLAG_ANS) && !sofia_test_flag(tech_pvt, TFLAG_EARLY_MEDIA)) {
sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
switch_log_printf(SWITCH_CHANNEL_ID_SESSION, msg->_file, msg->_func, msg->_line,
(const char*)session, SWITCH_LOG_INFO, "Sending early media\n");
/* Transmit 183 Progress with SDP */
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
const char *sdp = NULL;
if ((sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE))) {
2012-12-22 00:06:09 +00:00
switch_core_media_set_local_sdp(session, sdp, SWITCH_TRUE);
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
}
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
2012-12-22 00:06:09 +00:00
switch_core_media_patch_sdp(tech_pvt->session);
2012-12-18 22:06:29 +00:00
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
status = SWITCH_STATUS_FALSE;
goto end_lock;
}
}
} else {
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) ||
2012-12-22 00:06:09 +00:00
switch_core_media_codec_chosen(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO) != SWITCH_STATUS_SUCCESS) {
sofia_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION);
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
2012-12-22 00:06:09 +00:00
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
if (zstr(r_sdp) || sofia_media_tech_media(tech_pvt, r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"CODEC NEGOTIATION ERROR. SDP:\n%s\n", r_sdp ? r_sdp : "NO SDP!");
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
//nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
status = SWITCH_STATUS_FALSE;
goto end_lock;
}
}
}
2012-03-29 23:37:10 +00:00
switch_channel_check_zrtp(tech_pvt->channel);
2012-12-22 00:06:09 +00:00
if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
goto end_lock;
}
2013-11-07 22:48:00 +00:00
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
2012-12-18 22:06:29 +00:00
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
2012-12-22 00:06:09 +00:00
if (tech_pvt->mparams.local_sdp_str) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ring SDP:\n%s\n", tech_pvt->mparams.local_sdp_str);
}
}
switch_channel_mark_pre_answered(channel);
if (sofia_test_flag(tech_pvt, TFLAG_NAT) ||
(val = switch_channel_get_variable(channel, "sip-force-contact")) ||
((val = switch_channel_get_variable(channel, "sip_sticky_contact")) && switch_true(val))) {
sticky = tech_pvt->record_route;
switch_channel_set_variable(channel, "sip_nat_detected", "true");
}
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *extra_header = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
char *cid = NULL;
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
2010-10-06 13:38:32 +00:00
cid = generate_pai_str(tech_pvt);
2010-06-23 18:22:52 +00:00
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) &&
2012-12-22 00:06:09 +00:00
tech_pvt->mparams.early_sdp && strcmp(tech_pvt->mparams.early_sdp, tech_pvt->mparams.local_sdp_str)) {
/* The SIP RFC for SOA forbids sending a 183 with one sdp then a 200 with another but it won't do us much good unless
2010-06-18 21:52:39 +00:00
we do so in this case we will abandon the SOA rules and go rogue.
2010-06-30 15:35:03 +00:00
*/
2010-06-18 21:52:39 +00:00
sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
}
2012-12-22 00:06:09 +00:00
tech_pvt->mparams.early_sdp = switch_core_session_strdup(tech_pvt->session, tech_pvt->mparams.local_sdp_str);
2010-06-18 20:42:14 +00:00
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh,
send_sip_code, p_send_sip_msg,
NUTAG_AUTOANSWER(0),
TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SOATAG_REUSE_REJECTED(1),
2010-11-08 16:13:35 +00:00
SOATAG_RTP_SELECT(1),
2012-12-22 00:06:09 +00:00
SOATAG_ADDRESS(tech_pvt->mparams.adv_sdp_audio_ip),
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str), SOATAG_AUDIO_AUX("cn telephone-event"),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(!zstr(extra_header), SIPTAG_HEADER_STR(extra_header)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
} else {
nua_respond(tech_pvt->nh,
send_sip_code, p_send_sip_msg,
NUTAG_AUTOANSWER(0),
NUTAG_MEDIA_ENABLE(0),
TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
2012-12-22 00:06:09 +00:00
SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(!zstr(extra_header), SIPTAG_HEADER_STR(extra_header)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
switch_safe_free(extra_header);
}
}
}
break;
2012-12-22 00:06:09 +00:00
case SWITCH_MESSAGE_INDICATE_UDPTL_MODE:
{
switch_t38_options_t *t38_options = switch_channel_get_private(channel, "t38_options");
2012-12-22 00:06:09 +00:00
if (!t38_options) {
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
}
}
break;
case SWITCH_MESSAGE_INDICATE_SESSION_ID:
{
if (sofia_test_pflag(tech_pvt->profile, PFLAG_RFC7989_SESSION_ID) && switch_channel_test_flag(channel, CF_ANSWERED)) {
sofia_glue_do_invite(session);
2012-12-22 00:06:09 +00:00
}
}
break;
default:
break;
}
2010-06-30 15:35:03 +00:00
end_lock:
//if (msg->message_id == SWITCH_MESSAGE_INDICATE_ANSWER || msg->message_id == SWITCH_MESSAGE_INDICATE_PROGRESS) {
//sofia_send_callee_id(session, NULL, NULL);
//}
switch_mutex_unlock(tech_pvt->sofia_mutex);
2010-06-30 15:35:03 +00:00
end:
if (switch_channel_down(channel) || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
status = SWITCH_STATUS_FALSE;
}
return status;
}
static switch_status_t sofia_receive_event(switch_core_session_t *session, switch_event_t *event)
{
struct private_object *tech_pvt = switch_core_session_get_private(session);
char *body;
nua_handle_t *msg_nh;
switch_assert(tech_pvt != NULL);
if (!(body = switch_event_get_body(event))) {
body = "";
}
if (tech_pvt->hash_key) {
switch_mutex_lock(tech_pvt->sofia_mutex);
msg_nh = nua_handle(tech_pvt->profile->nua, NULL,
SIPTAG_FROM_STR(tech_pvt->chat_from),
2011-10-22 02:38:11 +00:00
NUTAG_URL(tech_pvt->chat_to), SIPTAG_TO_STR(tech_pvt->chat_to), TAG_END());
nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private);
nua_message(msg_nh, SIPTAG_CONTENT_TYPE_STR("text/html"), SIPTAG_PAYLOAD_STR(body), TAG_END());
switch_mutex_unlock(tech_pvt->sofia_mutex);
}
return SWITCH_STATUS_SUCCESS;
}
typedef switch_status_t (*sofia_command_t) (char **argv, int argc, switch_stream_handle_t *stream);
const char *sofia_state_names[] = {
"UNREGED",
"TRYING",
"REGISTER",
"REGED",
"UNREGISTER",
"FAILED",
"FAIL_WAIT",
"EXPIRED",
"NOREG",
"TIMEOUT",
NULL
};
const char *sofia_state_string(int state)
{
if (state >= REG_STATE_LAST) return "";
return sofia_state_names[state];
}
struct cb_helper_sql2str {
2010-06-23 18:22:52 +00:00
char *buf;
size_t len;
int matches;
};
struct cb_helper {
uint32_t row_process;
sofia_profile_t *profile;
switch_stream_handle_t *stream;
switch_bool_t dedup;
};
static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct cb_helper *cb = (struct cb_helper *) pArg;
char exp_buf[128] = "";
int exp_secs = 0;
switch_time_exp_t tm;
cb->row_process++;
if (argv[6]) {
time_t now = switch_epoch_time_now(NULL);
switch_time_t etime = atoi(argv[6]);
switch_size_t retsize;
2010-06-23 18:22:52 +00:00
exp_secs = (int)(etime - now);
switch_time_exp_lt(&tm, switch_time_from_sec(etime));
switch_strftime_nocheck(exp_buf, &retsize, sizeof(exp_buf), "%Y-%m-%d %T", &tm);
}
cb->stream->write_function(cb->stream,
"Call-ID: \t%s\n"
"User: \t%s@%s\n"
"Contact: \t%s\n"
"Agent: \t%s\n"
"Status: \t%s(%s) EXP(%s) EXPSECS(%d)\n"
"Ping-Status:\t%s\n"
"Ping-Time:\t%0.2f\n"
"Host: \t%s\n"
"IP: \t%s\n"
"Port: \t%s\n"
"Auth-User: \t%s\n"
"Auth-Realm: \t%s\n"
"MWI-Account:\t%s@%s\n\n",
switch_str_nil(argv[0]), switch_str_nil(argv[1]), switch_str_nil(argv[2]), switch_str_nil(argv[3]),
switch_str_nil(argv[7]), switch_str_nil(argv[4]), switch_str_nil(argv[5]), exp_buf, exp_secs, switch_str_nil(argv[18]),
(float)atoll(switch_str_nil(argv[19]))/1000, switch_str_nil(argv[11]), switch_str_nil(argv[12]),
switch_str_nil(argv[13]), switch_str_nil(argv[14]),
switch_str_nil(argv[15]), switch_str_nil(argv[16]), switch_str_nil(argv[17]));
return 0;
}
static int show_reg_callback_xml(void *pArg, int argc, char **argv, char **columnNames)
{
struct cb_helper *cb = (struct cb_helper *) pArg;
char exp_buf[128] = "";
switch_time_exp_t tm;
const int buflen = 2048;
char xmlbuf[2048];
int exp_secs = 0;
cb->row_process++;
if (argv[6]) {
time_t now = switch_epoch_time_now(NULL);
switch_time_t etime = atoi(argv[6]);
switch_size_t retsize;
exp_secs = (int)(etime - now);
switch_time_exp_lt(&tm, switch_time_from_sec(etime));
switch_strftime_nocheck(exp_buf, &retsize, sizeof(exp_buf), "%Y-%m-%d %T", &tm);
}
2010-06-23 18:22:52 +00:00
cb->stream->write_function(cb->stream, " <registration>\n");
cb->stream->write_function(cb->stream, " <call-id>%s</call-id>\n", switch_str_nil(argv[0]));
cb->stream->write_function(cb->stream, " <user>%s@%s</user>\n", switch_str_nil(argv[1]), switch_str_nil(argv[2]));
cb->stream->write_function(cb->stream, " <contact>%s</contact>\n", switch_amp_encode(switch_str_nil(argv[3]), xmlbuf, buflen));
2012-09-04 17:29:58 +00:00
cb->stream->write_function(cb->stream, " <agent>%s</agent>\n", switch_amp_encode(switch_str_nil(argv[7]), xmlbuf, buflen));
2010-06-23 18:22:52 +00:00
cb->stream->write_function(cb->stream, " <status>%s(%s) exp(%s) expsecs(%d)</status>\n", switch_str_nil(argv[4]), switch_str_nil(argv[5]),
exp_buf, exp_secs);
cb->stream->write_function(cb->stream, " <ping-status>%s</ping-status>\n", switch_str_nil(argv[18]));
cb->stream->write_function(cb->stream, " <ping-time>%0.2f</ping-time>\n", (float)atoll(switch_str_nil(argv[19]))/1000);
2010-06-23 18:22:52 +00:00
cb->stream->write_function(cb->stream, " <host>%s</host>\n", switch_str_nil(argv[11]));
cb->stream->write_function(cb->stream, " <network-ip>%s</network-ip>\n", switch_str_nil(argv[12]));
cb->stream->write_function(cb->stream, " <network-port>%s</network-port>\n", switch_str_nil(argv[13]));
cb->stream->write_function(cb->stream, " <sip-auth-user>%s</sip-auth-user>\n",
switch_url_encode(switch_str_nil(argv[14]), xmlbuf, sizeof(xmlbuf)));
cb->stream->write_function(cb->stream, " <sip-auth-realm>%s</sip-auth-realm>\n", switch_str_nil(argv[15]));
cb->stream->write_function(cb->stream, " <mwi-account>%s@%s</mwi-account>\n", switch_str_nil(argv[16]), switch_str_nil(argv[17]));
cb->stream->write_function(cb->stream, " </registration>\n");
return 0;
}
2012-02-28 16:17:08 +00:00
static int sql2str_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct cb_helper_sql2str *cbt = (struct cb_helper_sql2str *) pArg;
2012-02-28 16:17:08 +00:00
switch_copy_string(cbt->buf, argv[0], cbt->len);
cbt->matches++;
return 0;
}
uint32_t sofia_profile_reg_count(sofia_profile_t *profile)
2012-02-28 16:17:08 +00:00
{
struct cb_helper_sql2str cb;
char reg_count[80] = "";
char *sql;
cb.buf = reg_count;
cb.len = sizeof(reg_count);
sql = switch_mprintf("select count(*) from sip_registrations where profile_name = '%q'", profile->name);
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sql2str_callback, &cb);
2012-02-28 16:17:08 +00:00
free(sql);
return strtoul(reg_count, NULL, 10);
}
static const char *status_names[] = { "DOWN", "UP", NULL };
static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t *stream)
{
sofia_profile_t *profile = NULL;
sofia_gateway_t *gp;
switch_hash_index_t *hi;
void *val;
const void *vvar;
int c = 0;
int ac = 0;
const char *line = "=================================================================================================";
if (argc > 0) {
if (argc == 1) {
2010-06-23 18:22:52 +00:00
/* show summary of all gateways */
uint32_t ib_failed = 0;
uint32_t ib = 0;
uint32_t ob_failed = 0;
uint32_t ob = 0;
stream->write_function(stream, "%25s\t%32s\t%s\t%9s\t%s\t%s\n", "Profile::Gateway-Name", " Data ", "State", "Ping Time", "IB Calls(F/T)", "OB Calls(F/T)");
stream->write_function(stream, "%s\n", line);
switch_mutex_lock(mod_sofia_globals.hash_mutex);
2014-04-01 22:21:29 +00:00
for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
switch_core_hash_this(hi, &vvar, NULL, &val);
profile = (sofia_profile_t *) val;
if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
2010-06-23 18:22:52 +00:00
if (!strcmp(vvar, profile->name)) { /* not an alias */
for (gp = profile->gateways; gp; gp = gp->next) {
char *pkey = switch_mprintf("%s::%s", profile->name, gp->name);
switch_assert(gp->state < REG_STATE_LAST);
c++;
ib_failed += gp->ib_failed_calls;
ib += gp->ib_calls;
ob_failed += gp->ob_failed_calls;
ob += gp->ob_calls;
stream->write_function(stream, "%25s\t%32s\t%s\t%6.2f\t%u/%u\t%u/%u",
pkey, gp->register_to, sofia_state_names[gp->state], gp->ping_time,
2010-06-23 18:22:52 +00:00
gp->ib_failed_calls, gp->ib_calls, gp->ob_failed_calls, gp->ob_calls);
2015-12-10 04:36:41 +00:00
free(pkey);
if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) {
time_t now = switch_epoch_time_now(NULL);
2010-11-03 17:22:01 +00:00
if (gp->reg_timeout > now) {
stream->write_function(stream, " (retry: %ds)", gp->reg_timeout - now);
} else {
stream->write_function(stream, " (retry: NEVER)");
}
}
stream->write_function(stream, "\n");
}
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
stream->write_function(stream, "%s\n", line);
stream->write_function(stream, "%d gateway%s: Inbound(Failed/Total): %u/%u,"
"Outbound(Failed/Total):%u/%u\n", c, c == 1 ? "" : "s", ib_failed, ib, ob_failed, ob);
return SWITCH_STATUS_SUCCESS;
}
if (!strcasecmp(argv[0], "gateway")) {
if ((gp = sofia_reg_find_gateway(argv[1]))) {
switch_assert(gp->state < REG_STATE_LAST);
stream->write_function(stream, "%s\n", line);
stream->write_function(stream, "Name \t%s\n", switch_str_nil(gp->name));
stream->write_function(stream, "Profile \t%s\n", gp->profile->name);
stream->write_function(stream, "Scheme \t%s\n", switch_str_nil(gp->register_scheme));
stream->write_function(stream, "Realm \t%s\n", switch_str_nil(gp->register_realm));
stream->write_function(stream, "Username\t%s\n", switch_str_nil(gp->register_username));
stream->write_function(stream, "Password\t%s\n", zstr(gp->register_password) ? "no" : "yes");
stream->write_function(stream, "From \t%s\n", switch_str_nil(gp->register_from));
stream->write_function(stream, "Contact \t%s\n", switch_str_nil(gp->register_contact));
stream->write_function(stream, "Exten \t%s\n", switch_str_nil(gp->extension));
stream->write_function(stream, "To \t%s\n", switch_str_nil(gp->register_to));
stream->write_function(stream, "Proxy \t%s\n", switch_str_nil(gp->register_proxy));
stream->write_function(stream, "Context \t%s\n", switch_str_nil(gp->register_context));
stream->write_function(stream, "Expires \t%s\n", switch_str_nil(gp->expires_str));
stream->write_function(stream, "Freq \t%d\n", gp->freq);
stream->write_function(stream, "Ping \t%d\n", gp->ping);
stream->write_function(stream, "PingFreq\t%d\n", gp->ping_freq);
stream->write_function(stream, "PingTime\t%0.2f\n", gp->ping_time);
stream->write_function(stream, "PingState\t%d/%d/%d\n", gp->ping_min, gp->ping_count, gp->ping_max);
stream->write_function(stream, "State \t%s\n", sofia_state_names[gp->state]);
stream->write_function(stream, "Status \t%s%s\n", status_names[gp->status], gp->pinging ? " (ping)" : "");
stream->write_function(stream, "Uptime \t%lds\n", gp->status == SOFIA_GATEWAY_UP ? (switch_time_now()-gp->uptime)/1000000 : 0);
stream->write_function(stream, "CallsIN \t%u\n", gp->ib_calls);
stream->write_function(stream, "CallsOUT\t%u\n", gp->ob_calls);
stream->write_function(stream, "FailedCallsIN\t%u\n", gp->ib_failed_calls);
stream->write_function(stream, "FailedCallsOUT\t%u\n", gp->ob_failed_calls);
stream->write_function(stream, "%s\n", line);
sofia_reg_release_gateway(gp);
} else {
stream->write_function(stream, "Invalid Gateway!\n");
}
} else if (!strcasecmp(argv[0], "profile")) {
struct cb_helper cb;
char *sql = NULL;
uint32_t x = 0;
cb.row_process = 0;
if ((argv[1]) && (profile = sofia_glue_find_profile(argv[1]))) {
if (!argv[2] || (strcasecmp(argv[2], "reg") && strcasecmp(argv[2], "user"))) {
stream->write_function(stream, "%s\n", line);
stream->write_function(stream, "Name \t%s\n", switch_str_nil(argv[1]));
stream->write_function(stream, "Domain Name \t%s\n", profile->domain_name ? profile->domain_name : "N/A");
if (strcasecmp(argv[1], profile->name)) {
stream->write_function(stream, "Alias Of \t%s\n", switch_str_nil(profile->name));
}
stream->write_function(stream, "Auto-NAT \t%s\n", sofia_test_pflag(profile, PFLAG_AUTO_NAT) ? "true" : "false");
stream->write_function(stream, "DBName \t%s\n", profile->dbname ? profile->dbname : switch_str_nil(profile->odbc_dsn));
stream->write_function(stream, "Pres Hosts \t%s\n", switch_str_nil(profile->presence_hosts));
stream->write_function(stream, "Dialplan \t%s\n", switch_str_nil(profile->dialplan));
stream->write_function(stream, "Context \t%s\n", switch_str_nil(profile->context));
stream->write_function(stream, "Challenge Realm \t%s\n", zstr(profile->challenge_realm) ? "auto_to" : profile->challenge_realm);
for (x = 0; x < profile->rtpip_index; x++) {
stream->write_function(stream, "RTP-IP \t%s\n", switch_str_nil(profile->rtpip[x]));
}
for (x = 0; x < profile->rtpip_index6; x++) {
stream->write_function(stream, "RTP-IP \t%s\n", switch_str_nil(profile->rtpip6[x]));
}
if (profile->extrtpip) {
stream->write_function(stream, "Ext-RTP-IP \t%s\n", profile->extrtpip);
}
stream->write_function(stream, "SIP-IP \t%s\n", switch_str_nil(profile->sipip));
if (profile->extsipip) {
stream->write_function(stream, "Ext-SIP-IP \t%s\n", profile->extsipip);
}
if (! sofia_test_pflag(profile, PFLAG_TLS) || ! profile->tls_only) {
stream->write_function(stream, "URL \t%s\n", switch_str_nil(profile->url));
stream->write_function(stream, "BIND-URL \t%s\n", switch_str_nil(profile->bindurl));
}
if (sofia_test_pflag(profile, PFLAG_TLS)) {
stream->write_function(stream, "TLS-URL \t%s\n", switch_str_nil(profile->tls_url));
stream->write_function(stream, "TLS-BIND-URL \t%s\n", switch_str_nil(profile->tls_bindurl));
}
2014-02-07 17:34:34 +00:00
if (profile->ws_bindurl) {
stream->write_function(stream, "WS-BIND-URL \t%s\n", switch_str_nil(profile->ws_bindurl));
}
if (profile->wss_bindurl) {
stream->write_function(stream, "WSS-BIND-URL \t%s\n", switch_str_nil(profile->wss_bindurl));
}
stream->write_function(stream, "HOLD-MUSIC \t%s\n", zstr(profile->hold_music) ? "N/A" : profile->hold_music);
stream->write_function(stream, "OUTBOUND-PROXY \t%s\n", zstr(profile->outbound_proxy) ? "N/A" : profile->outbound_proxy);
stream->write_function(stream, "CODECS IN \t%s\n", switch_str_nil(profile->inbound_codec_string));
stream->write_function(stream, "CODECS OUT \t%s\n", switch_str_nil(profile->outbound_codec_string));
stream->write_function(stream, "TEL-EVENT \t%d\n", profile->te);
if (profile->dtmf_type == DTMF_2833) {
stream->write_function(stream, "DTMF-MODE \trfc2833\n");
} else if (profile->dtmf_type == DTMF_INFO) {
stream->write_function(stream, "DTMF-MODE \tinfo\n");
} else {
stream->write_function(stream, "DTMF-MODE \tnone\n");
}
stream->write_function(stream, "CNG \t%d\n", profile->cng_pt);
stream->write_function(stream, "SESSION-TO \t%d\n", profile->session_timeout);
stream->write_function(stream, "MAX-DIALOG \t%d\n", profile->max_proceeding);
stream->write_function(stream, "NOMEDIA \t%s\n", sofia_test_flag(profile, TFLAG_INB_NOMEDIA) ? "true" : "false");
stream->write_function(stream, "LATE-NEG \t%s\n", sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION) ? "true" : "false");
stream->write_function(stream, "PROXY-MEDIA \t%s\n", sofia_test_flag(profile, TFLAG_PROXY_MEDIA) ? "true" : "false");
add enhanced zrtp passthrough (zrtp passthru) mode ZRTP passthrough mode allows two ZRTP-capable clients to negotiate an end-to-end security association through FreeSWITCH. The clients are therefore able to be certain that the FreeSWITCH instance mediating the call cannot eavesdrop on their conversation. Importantly, this capability is maintained across multiple FreeSWITCH hops. If widely deployed, this enables a global network architecture where two people can speak securely with strong cryptographically protected authentication and confidentiality. With this commit we implement a zrtp-passthru mode that handles all the details of the negotiation intelligently. This mode can be selected by setting the boolean parameter inbound-zrtp-passthru in the sofia profile. This will also force late-negotiation as it is essential for correctly negotiating an end-to-end ZRTP security association. When an incoming call with a zrtp-hash is received and this mode is enabled, we find the first audio and the first video zrtp-hash in the SDP and store them as remote values on this channel. Once a b-leg is available, we set the local zrtp-hash values on that channel to the remote zrtp-hash values collected from the a-leg. Because zrtp-passthru absolutely requires that the channels negotiate the same codec, we offer to the b-leg only codecs that the a-leg can speak. Once the b-leg accepts a codec, we will force that choice onto the a-leg. If the b-leg sends us zrtp-hash values in the signaling, we store those as remote values on the b-leg and copy them to the local values on the a-leg. At this point, each leg has the zrtp-hash values from the other, and we know we can do ZRTP passthrough mode on the call. We send the b-leg's zrtp-hash back to the a-leg in the 200 OK. We then enable UDPTL mode on the rtp streams for both the audio and the video so that we don't interfere in the ZRTP negotiation. If the b-leg fails to return a zrtp-hash in the signaling, we set up a ZRTP security association with the a-leg ourselves, if we are so equipped. Likewise, if the a-leg fails to send a zrtp-hash in the signaling, we attempt to set up a ZRTP security association ourselves with the b-leg. The zrtp-passthru mode can also be enabled in the dialplan by setting the boolean channel variable zrtp_passthru. If enabled in this manner, we can't force late-negotiation, so the user would need to be sure this is configured. If ZRTP passthrough mode is not enabled in either manner, this change should have no effect. Channel variables for each of the various zrtp-hash values are set, though it is anticipated that there is no good reason to use them, so they may be removed without warning. For checking whether zrtp passthrough mode was successful, we provide the channel variable zrtp_passthru_active which is set on both legs. Though not implemented by this commit, the changes here should make it more straightforward to add correct zrtp-hash values to the signaling and verify that correct hello hash values are received when FreeSWITCH is acting as a terminating leg of the ZRTP security association. A historical note... This commit replaces the recently-added sdp_zrtp_hash_string method, commit 2ab1605a8887adc62be1b75f6ef67af87ff080de. This prior method sets a channel variable from the a-leg's zrtp-hash, then relies on the dialplan to export this channel variable to the b-leg, where it is put into the SDP. While it was a great start and wonderful for testing, this approach has some drawbacks that motivated the present work: * There's no good way to pass the zrtp-hash from the b-leg back to the a-leg. In fact, the implementation seems to send the a-leg's zrtp-hash back to the originating client in the 200 OK. This is not correct. * To support video, we'd need to have a separate dialplan variable, and the dialplan author would need to deal with that explicitly. * The API is problematic as it requires the dialplan author to understand intricate details of how ZRTP works to implement a correct dialplan. Further, by providing too fine-grained control (but at the same time, not enough control) it would limit our ability to make the behavior smarter once people started relying on this.
2012-05-24 20:39:03 +00:00
stream->write_function(stream, "ZRTP-PASSTHRU \t%s\n", sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU) ? "true" : "false");
stream->write_function(stream, "AGGRESSIVENAT \t%s\n",
sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION) ? "true" : "false");
if (profile->user_agent_filter) {
stream->write_function(stream, "USER-AGENT-FILTER\t%s\n", switch_str_nil(profile->user_agent_filter));
}
if (profile->max_registrations_perext > 0) {
stream->write_function(stream, "MAX-REG-PEREXT \t%d\n", profile->max_registrations_perext);
}
stream->write_function(stream, "CALLS-IN \t%u\n", profile->ib_calls);
stream->write_function(stream, "FAILED-CALLS-IN \t%u\n", profile->ib_failed_calls);
stream->write_function(stream, "CALLS-OUT \t%u\n", profile->ob_calls);
stream->write_function(stream, "FAILED-CALLS-OUT \t%u\n", profile->ob_failed_calls);
2012-02-28 16:17:08 +00:00
stream->write_function(stream, "REGISTRATIONS \t%lu\n", sofia_profile_reg_count(profile));
}
cb.profile = profile;
cb.stream = stream;
if (argv[2] && !strcasecmp(argv[2], "pres") && argv[3]) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q' and presence_hosts like '%%%q%%'", profile->name, argv[3]);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "reg") && argv[3]) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host, ping_status,ping_time"
" from sip_registrations where profile_name='%q' and contact like '%%%q%%'", profile->name, argv[3]);
}
2011-11-17 22:25:50 +00:00
if (!sql && argv[2] && !strcasecmp(argv[2], "reg")) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
2011-11-17 22:25:50 +00:00
" from sip_registrations where profile_name='%q'", profile->name);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "user") && argv[3]) {
char *dup = strdup(argv[3]);
char *host = NULL, *user = NULL;
char *sqlextra = NULL;
switch_assert(dup);
if ((host = strchr(dup, '@'))) {
*host++ = '\0';
user = dup;
} else {
host = dup;
}
if (zstr(user)) {
sqlextra = switch_mprintf("(sip_host='%q')", host);
} else if (zstr(host)) {
sqlextra = switch_mprintf("(sip_user='%q')", user);
} else {
sqlextra = switch_mprintf("(sip_user='%q' and sip_host='%q')", user, host);
}
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q' and %s", profile->name, sqlextra);
switch_safe_free(dup);
switch_safe_free(sqlextra);
}
2011-11-17 22:25:50 +00:00
if (sql) {
stream->write_function(stream, "\nRegistrations:\n%s\n", line);
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, show_reg_callback, &cb);
2011-11-17 22:25:50 +00:00
switch_safe_free(sql);
2011-11-17 22:25:50 +00:00
stream->write_function(stream, "Total items returned: %d\n", cb.row_process);
stream->write_function(stream, "%s\n", line);
}
sofia_glue_release_profile(profile);
2011-11-17 22:25:50 +00:00
} else {
stream->write_function(stream, "Invalid Profile!\n");
}
} else {
stream->write_function(stream, "Invalid Syntax!\n");
}
return SWITCH_STATUS_SUCCESS;
}
stream->write_function(stream, "%25s\t%s\t %40s\t%s\n", "Name", " Type", "Data", "State");
stream->write_function(stream, "%s\n", line);
switch_mutex_lock(mod_sofia_globals.hash_mutex);
2014-04-01 22:21:29 +00:00
for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
switch_core_hash_this(hi, &vvar, NULL, &val);
profile = (sofia_profile_t *) val;
if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
if (strcmp(vvar, profile->name)) {
ac++;
stream->write_function(stream, "%25s\t%s\t %40s\t%s\n", vvar, " alias", profile->name, "ALIASED");
} else {
if (! sofia_test_pflag(profile, PFLAG_TLS) || ! profile->tls_only) {
stream->write_function(stream, "%25s\t%s\t %40s\t%s (%u)\n", profile->name, "profile", profile->url,
sofia_test_pflag(profile, PFLAG_RUNNING) ? "RUNNING" : "DOWN", profile->inuse);
}
if (sofia_test_pflag(profile, PFLAG_TLS)) {
stream->write_function(stream, "%25s\t%s\t %40s\t%s (%u) (TLS)\n", profile->name, "profile", profile->tls_url,
sofia_test_pflag(profile, PFLAG_RUNNING) ? "RUNNING" : "DOWN", profile->inuse);
}
c++;
for (gp = profile->gateways; gp; gp = gp->next) {
char *pkey = switch_mprintf("%s::%s", profile->name, gp->name);
switch_assert(gp->state < REG_STATE_LAST);
2010-06-23 18:22:52 +00:00
stream->write_function(stream, "%25s\t%s\t %40s\t%s", pkey, "gateway", gp->register_to, sofia_state_names[gp->state]);
free(pkey);
if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) {
time_t now = switch_epoch_time_now(NULL);
if (gp->retry > now) {
stream->write_function(stream, " (retry: %ds)", gp->retry - now);
} else {
stream->write_function(stream, " (retry: NEVER)");
}
}
stream->write_function(stream, "\n");
}
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
stream->write_function(stream, "%s\n", line);
stream->write_function(stream, "%d profile%s %d alias%s\n", c, c == 1 ? "" : "s", ac, ac == 1 ? "" : "es");
return SWITCH_STATUS_SUCCESS;
}
static void xml_gateway_status(sofia_gateway_t *gp, switch_stream_handle_t *stream)
{
char xmlbuf[2096];
const int buflen = 2096;
stream->write_function(stream, " <gateway>\n");
stream->write_function(stream, " <name>%s</name>\n", switch_str_nil(gp->name));
stream->write_function(stream, " <profile>%s</profile>\n", gp->profile->name);
stream->write_function(stream, " <scheme>%s</scheme>\n", switch_str_nil(gp->register_scheme));
stream->write_function(stream, " <realm>%s</realm>\n", switch_str_nil(gp->register_realm));
stream->write_function(stream, " <username>%s</username>\n", switch_str_nil(gp->register_username));
stream->write_function(stream, " <password>%s</password>\n", zstr(gp->register_password) ? "no" : "yes");
stream->write_function(stream, " <from>%s</from>\n", switch_amp_encode(switch_str_nil(gp->register_from), xmlbuf, buflen));
stream->write_function(stream, " <contact>%s</contact>\n", switch_amp_encode(switch_str_nil(gp->register_contact), xmlbuf, buflen));
stream->write_function(stream, " <exten>%s</exten>\n", switch_amp_encode(switch_str_nil(gp->extension), xmlbuf, buflen));
stream->write_function(stream, " <to>%s</to>\n", switch_str_nil(gp->register_to));
stream->write_function(stream, " <proxy>%s</proxy>\n", switch_str_nil(gp->register_proxy));
stream->write_function(stream, " <context>%s</context>\n", switch_str_nil(gp->register_context));
stream->write_function(stream, " <expires>%s</expires>\n", switch_str_nil(gp->expires_str));
stream->write_function(stream, " <freq>%d</freq>\n", gp->freq);
stream->write_function(stream, " <ping>%d</ping>\n", gp->ping);
stream->write_function(stream, " <pingfreq>%d</pingfreq>\n", gp->ping_freq);
2013-09-04 16:05:13 +00:00
stream->write_function(stream, " <pingmin>%d</pingmin>\n", gp->ping_min);
stream->write_function(stream, " <pingcount>%d</pingcount>\n", gp->ping_count);
2013-09-04 16:05:13 +00:00
stream->write_function(stream, " <pingmax>%d</pingmax>\n", gp->ping_max);
stream->write_function(stream, " <pingtime>%0.2f</pingtime>\n", gp->ping_time);
2013-09-04 16:05:13 +00:00
stream->write_function(stream, " <pinging>%d</pinging>\n", gp->pinging);
stream->write_function(stream, " <state>%s</state>\n", sofia_state_names[gp->state]);
2013-09-04 16:05:13 +00:00
stream->write_function(stream, " <status>%s</status>\n", status_names[gp->status]);
stream->write_function(stream, " <uptime-usec>%ld</uptime-usec>\n", gp->status == SOFIA_GATEWAY_UP ? switch_time_now()-gp->uptime : 0);
stream->write_function(stream, " <calls-in>%u</calls-in>\n", gp->ib_calls);
stream->write_function(stream, " <calls-out>%u</calls-out>\n", gp->ob_calls);
stream->write_function(stream, " <failed-calls-in>%u</failed-calls-in>\n", gp->ib_failed_calls);
stream->write_function(stream, " <failed-calls-out>%u</failed-calls-out>\n", gp->ob_failed_calls);
if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) {
time_t now = switch_epoch_time_now(NULL);
if (gp->retry > now) {
stream->write_function(stream, " <retry>%ds</retry>\n", gp->retry - now);
} else {
stream->write_function(stream, " <retry>NEVER</retry>\n");
}
}
stream->write_function(stream, " </gateway>\n");
}
static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handle_t *stream)
{
sofia_profile_t *profile = NULL;
sofia_gateway_t *gp;
switch_hash_index_t *hi;
void *val;
const void *vvar;
int c = 0;
int ac = 0;
const char *header = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
if (argc > 0) {
if (argc == 1) {
2010-06-23 18:22:52 +00:00
/* show summary of all gateways */
stream->write_function(stream, "%s\n", header);
stream->write_function(stream, "<gateways>\n", header);
switch_mutex_lock(mod_sofia_globals.hash_mutex);
2014-04-01 22:21:29 +00:00
for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
switch_core_hash_this(hi, &vvar, NULL, &val);
2010-06-23 18:22:52 +00:00
profile = (sofia_profile_t *) val;
if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
if (!strcmp(vvar, profile->name)) { /* not an alias */
for (gp = profile->gateways; gp; gp = gp->next) {
switch_assert(gp->state < REG_STATE_LAST);
xml_gateway_status(gp, stream);
2010-06-23 18:22:52 +00:00
}
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
stream->write_function(stream, "</gateways>\n");
} else if (!strcasecmp(argv[0], "gateway")) {
if ((gp = sofia_reg_find_gateway(argv[1]))) {
switch_assert(gp->state < REG_STATE_LAST);
stream->write_function(stream, "%s\n", header);
xml_gateway_status(gp, stream);
sofia_reg_release_gateway(gp);
} else {
stream->write_function(stream, "Invalid Gateway!\n");
}
} else if (!strcasecmp(argv[0], "profile")) {
struct cb_helper cb;
char *sql = NULL;
uint32_t x = 0;
cb.row_process = 0;
if ((argv[1]) && (profile = sofia_glue_find_profile(argv[1]))) {
stream->write_function(stream, "%s\n", header);
stream->write_function(stream, "<profile>\n");
if (!argv[2] || (strcasecmp(argv[2], "reg") && strcasecmp(argv[2], "user"))) {
stream->write_function(stream, " <profile-info>\n");
stream->write_function(stream, " <name>%s</name>\n", switch_str_nil(argv[1]));
stream->write_function(stream, " <domain-name>%s</domain-name>\n", profile->domain_name ? profile->domain_name : "N/A");
if (strcasecmp(argv[1], profile->name)) {
stream->write_function(stream, " <alias-of>%s</alias-of>\n", switch_str_nil(profile->name));
}
stream->write_function(stream, " <auto-nat>%s</auto-nat>\n", sofia_test_pflag(profile, PFLAG_AUTO_NAT) ? "true" : "false");
stream->write_function(stream, " <db-name>%s</db-name>\n", profile->dbname ? profile->dbname : switch_str_nil(profile->odbc_dsn));
stream->write_function(stream, " <pres-hosts>%s</pres-hosts>\n", switch_str_nil(profile->presence_hosts));
stream->write_function(stream, " <dialplan>%s</dialplan>\n", switch_str_nil(profile->dialplan));
stream->write_function(stream, " <context>%s</context>\n", switch_str_nil(profile->context));
stream->write_function(stream, " <challenge-realm>%s</challenge-realm>\n",
zstr(profile->challenge_realm) ? "auto_to" : profile->challenge_realm);
for (x = 0; x < profile->rtpip_index; x++) {
stream->write_function(stream, " <rtp-ip>%s</rtp-ip>\n", switch_str_nil(profile->rtpip[x]));
}
for (x = 0; x < profile->rtpip_index6; x++) {
stream->write_function(stream, " <rtp-ip>%s</rtp-ip>\n", switch_str_nil(profile->rtpip6[x]));
}
2014-09-09 13:33:19 +00:00
if (profile->extrtpip) {
stream->write_function(stream, " <ext-rtp-ip>%s</ext-rtp-ip>\n", profile->extrtpip);
}
stream->write_function(stream, " <sip-ip>%s</sip-ip>\n", switch_str_nil(profile->sipip));
2014-09-09 13:33:19 +00:00
if (profile->extsipip) {
stream->write_function(stream, " <ext-sip-ip>%s</ext-sip-ip>\n", profile->extsipip);
}
if (! sofia_test_pflag(profile, PFLAG_TLS) || ! profile->tls_only) {
stream->write_function(stream, " <url>%s</url>\n", switch_str_nil(profile->url));
stream->write_function(stream, " <bind-url>%s</bind-url>\n", switch_str_nil(profile->bindurl));
}
if (sofia_test_pflag(profile, PFLAG_TLS)) {
stream->write_function(stream, " <tls-url>%s</tls-url>\n", switch_str_nil(profile->tls_url));
stream->write_function(stream, " <tls-bind-url>%s</tls-bind-url>\n", switch_str_nil(profile->tls_bindurl));
}
if (profile->ws_bindurl) {
stream->write_function(stream, " <ws-bind-url>%s</ws-bind-url>\n", switch_str_nil(profile->ws_bindurl));
}
if (profile->wss_bindurl) {
stream->write_function(stream, " <wss-bind-url>%s</wss-bind-url>\n", switch_str_nil(profile->wss_bindurl));
}
stream->write_function(stream, " <hold-music>%s</hold-music>\n", zstr(profile->hold_music) ? "N/A" : profile->hold_music);
stream->write_function(stream, " <outbound-proxy>%s</outbound-proxy>\n",
zstr(profile->outbound_proxy) ? "N/A" : profile->outbound_proxy);
stream->write_function(stream, " <inbound-codecs>%s</inbound-codecs>\n", switch_str_nil(profile->inbound_codec_string));
stream->write_function(stream, " <outbound-codecs>%s</outbound-codecs>\n", switch_str_nil(profile->outbound_codec_string));
stream->write_function(stream, " <tel-event>%d</tel-event>\n", profile->te);
2014-09-09 13:33:19 +00:00
if (profile->dtmf_type == DTMF_2833) {
stream->write_function(stream, " <dtmf-mode>rfc2833</dtmf-mode>\n");
} else if (profile->dtmf_type == DTMF_INFO) {
stream->write_function(stream, " <dtmf-mode>info</dtmf-mode>\n");
} else {
stream->write_function(stream, " <dtmf-mode>none</dtmf-mode>\n");
}
stream->write_function(stream, " <cng>%d</cng>\n", profile->cng_pt);
stream->write_function(stream, " <session-to>%d</session-to>\n", profile->session_timeout);
stream->write_function(stream, " <max-dialog>%d</max-dialog>\n", profile->max_proceeding);
stream->write_function(stream, " <nomedia>%s</nomedia>\n", sofia_test_flag(profile, TFLAG_INB_NOMEDIA) ? "true" : "false");
stream->write_function(stream, " <late-neg>%s</late-neg>\n", sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION) ? "true" : "false");
stream->write_function(stream, " <proxy-media>%s</proxy-media>\n", sofia_test_flag(profile, TFLAG_PROXY_MEDIA) ? "true" : "false");
add enhanced zrtp passthrough (zrtp passthru) mode ZRTP passthrough mode allows two ZRTP-capable clients to negotiate an end-to-end security association through FreeSWITCH. The clients are therefore able to be certain that the FreeSWITCH instance mediating the call cannot eavesdrop on their conversation. Importantly, this capability is maintained across multiple FreeSWITCH hops. If widely deployed, this enables a global network architecture where two people can speak securely with strong cryptographically protected authentication and confidentiality. With this commit we implement a zrtp-passthru mode that handles all the details of the negotiation intelligently. This mode can be selected by setting the boolean parameter inbound-zrtp-passthru in the sofia profile. This will also force late-negotiation as it is essential for correctly negotiating an end-to-end ZRTP security association. When an incoming call with a zrtp-hash is received and this mode is enabled, we find the first audio and the first video zrtp-hash in the SDP and store them as remote values on this channel. Once a b-leg is available, we set the local zrtp-hash values on that channel to the remote zrtp-hash values collected from the a-leg. Because zrtp-passthru absolutely requires that the channels negotiate the same codec, we offer to the b-leg only codecs that the a-leg can speak. Once the b-leg accepts a codec, we will force that choice onto the a-leg. If the b-leg sends us zrtp-hash values in the signaling, we store those as remote values on the b-leg and copy them to the local values on the a-leg. At this point, each leg has the zrtp-hash values from the other, and we know we can do ZRTP passthrough mode on the call. We send the b-leg's zrtp-hash back to the a-leg in the 200 OK. We then enable UDPTL mode on the rtp streams for both the audio and the video so that we don't interfere in the ZRTP negotiation. If the b-leg fails to return a zrtp-hash in the signaling, we set up a ZRTP security association with the a-leg ourselves, if we are so equipped. Likewise, if the a-leg fails to send a zrtp-hash in the signaling, we attempt to set up a ZRTP security association ourselves with the b-leg. The zrtp-passthru mode can also be enabled in the dialplan by setting the boolean channel variable zrtp_passthru. If enabled in this manner, we can't force late-negotiation, so the user would need to be sure this is configured. If ZRTP passthrough mode is not enabled in either manner, this change should have no effect. Channel variables for each of the various zrtp-hash values are set, though it is anticipated that there is no good reason to use them, so they may be removed without warning. For checking whether zrtp passthrough mode was successful, we provide the channel variable zrtp_passthru_active which is set on both legs. Though not implemented by this commit, the changes here should make it more straightforward to add correct zrtp-hash values to the signaling and verify that correct hello hash values are received when FreeSWITCH is acting as a terminating leg of the ZRTP security association. A historical note... This commit replaces the recently-added sdp_zrtp_hash_string method, commit 2ab1605a8887adc62be1b75f6ef67af87ff080de. This prior method sets a channel variable from the a-leg's zrtp-hash, then relies on the dialplan to export this channel variable to the b-leg, where it is put into the SDP. While it was a great start and wonderful for testing, this approach has some drawbacks that motivated the present work: * There's no good way to pass the zrtp-hash from the b-leg back to the a-leg. In fact, the implementation seems to send the a-leg's zrtp-hash back to the originating client in the 200 OK. This is not correct. * To support video, we'd need to have a separate dialplan variable, and the dialplan author would need to deal with that explicitly. * The API is problematic as it requires the dialplan author to understand intricate details of how ZRTP works to implement a correct dialplan. Further, by providing too fine-grained control (but at the same time, not enough control) it would limit our ability to make the behavior smarter once people started relying on this.
2012-05-24 20:39:03 +00:00
stream->write_function(stream, " <zrtp-passthru>%s</zrtp-passthru>\n", sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU) ? "true" : "false");
stream->write_function(stream, " <aggressive-nat>%s</aggressive-nat>\n",
sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION) ? "true" : "false");
2014-09-09 13:33:19 +00:00
if (profile->user_agent_filter) {
stream->write_function(stream, " <user-agent-filter>%s</user-agent-filter>\n", switch_str_nil(profile->user_agent_filter));
}
if (profile->max_registrations_perext > 0) {
stream->write_function(stream, " <max-registrations-per-extension>%d</max-registrations-per-extension>\n",
profile->max_registrations_perext);
2014-09-09 13:33:19 +00:00
}
stream->write_function(stream, " <calls-in>%u</calls-in>\n", profile->ib_calls);
stream->write_function(stream, " <calls-out>%u</calls-out>\n", profile->ob_calls);
stream->write_function(stream, " <failed-calls-in>%u</failed-calls-in>\n", profile->ib_failed_calls);
stream->write_function(stream, " <failed-calls-out>%u</failed-calls-out>\n", profile->ob_failed_calls);
2012-02-28 16:17:08 +00:00
stream->write_function(stream, " <registrations>%lu</registrations>\n", sofia_profile_reg_count(profile));
stream->write_function(stream, " </profile-info>\n");
}
cb.profile = profile;
cb.stream = stream;
if (argv[2] && !strcasecmp(argv[2], "pres") && argv[3]) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q' and presence_hosts like '%%%q%%'", profile->name, argv[3]);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "reg") && argv[3]) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q' and contact like '%%%q%%'", profile->name, argv[3]);
}
2012-02-28 16:17:08 +00:00
if (!sql && argv[2] && !strcasecmp(argv[2], "reg")) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
2012-02-28 16:17:08 +00:00
" from sip_registrations where profile_name='%q'", profile->name);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "user") && argv[3]) {
char *dup = strdup(argv[3]);
char *host = NULL, *user = NULL;
char *sqlextra = NULL;
switch_assert(dup);
if ((host = strchr(dup, '@'))) {
*host++ = '\0';
user = dup;
} else {
host = dup;
}
if (zstr(user)) {
sqlextra = switch_mprintf("(sip_host='%q')", host);
} else if (zstr(host)) {
sqlextra = switch_mprintf("(sip_user='%q')", user);
} else {
sqlextra = switch_mprintf("(sip_user='%q' and sip_host='%q')", user, host);
}
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
" from sip_registrations where profile_name='%q' and %s", profile->name, sqlextra);
switch_safe_free(dup);
switch_safe_free(sqlextra);
}
2012-02-28 16:17:08 +00:00
if (sql) {
stream->write_function(stream, " <registrations>\n");
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, show_reg_callback_xml, &cb);
2012-02-28 16:17:08 +00:00
switch_safe_free(sql);
2012-02-28 16:17:08 +00:00
stream->write_function(stream, " </registrations>\n");
}
stream->write_function(stream, "</profile>\n");
sofia_glue_release_profile(profile);
} else {
stream->write_function(stream, "Invalid Profile!\n");
}
} else {
stream->write_function(stream, "Invalid Syntax!\n");
}
return SWITCH_STATUS_SUCCESS;
}
stream->write_function(stream, "%s\n", header);
stream->write_function(stream, "<profiles>\n");
switch_mutex_lock(mod_sofia_globals.hash_mutex);
2014-04-01 22:21:29 +00:00
for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
switch_core_hash_this(hi, &vvar, NULL, &val);
profile = (sofia_profile_t *) val;
if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
if (strcmp(vvar, profile->name)) {
ac++;
stream->write_function(stream, "<alias>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s</state>\n</alias>\n", vvar, "alias",
profile->name, "ALIASED");
} else {
if (! sofia_test_pflag(profile, PFLAG_TLS) || ! profile->tls_only){
stream->write_function(stream, "<profile>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s (%u)</state>\n</profile>\n",
profile->name, "profile", profile->url, sofia_test_pflag(profile, PFLAG_RUNNING) ? "RUNNING" : "DOWN",
profile->inuse);
}
if (sofia_test_pflag(profile, PFLAG_TLS)) {
2014-02-07 17:34:34 +00:00
stream->write_function(stream, "<profile>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s (%u) (TLS)</state>\n</profile>\n",
profile->name, "profile", profile->tls_url, sofia_test_pflag(profile, PFLAG_RUNNING) ? "RUNNING" : "DOWN",
profile->inuse);
}
if (profile->ws_bindurl){
stream->write_function(stream, "<profile>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s (%u) (WS)</state>\n</profile>\n",
profile->name, "profile", profile->ws_bindurl, sofia_test_pflag(profile, PFLAG_RUNNING) ? "RUNNING" : "DOWN",
profile->inuse);
}
if (profile->wss_bindurl){
stream->write_function(stream, "<profile>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s (%u) (WSS)</state>\n</profile>\n",
profile->name, "profile", profile->wss_bindurl, sofia_test_pflag(profile, PFLAG_RUNNING) ? "RUNNING" : "DOWN",
profile->inuse);
}
c++;
for (gp = profile->gateways; gp; gp = gp->next) {
switch_assert(gp->state < REG_STATE_LAST);
stream->write_function(stream, "<gateway>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s</state>\n</gateway>\n",
gp->name, "gateway", gp->register_to, sofia_state_names[gp->state]);
if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) {
time_t now = switch_epoch_time_now(NULL);
if (gp->retry > now) {
stream->write_function(stream, " (retry: %ds)", gp->retry - now);
} else {
stream->write_function(stream, " (retry: NEVER)");
}
}
stream->write_function(stream, "\n");
}
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
stream->write_function(stream, "</profiles>\n");
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t *stream)
{
sofia_profile_t *profile = NULL;
char *profile_name = argv[0];
const char *err;
if (argc < 2) {
stream->write_function(stream, "Invalid Args!\n");
return SWITCH_STATUS_SUCCESS;
}
if (!strcasecmp(argv[1], "start")) {
2010-09-16 23:17:52 +00:00
switch_xml_reload(&err);
stream->write_function(stream, "Reload XML [%s]\n", err);
if (config_sofia(SOFIA_CONFIG_RESCAN, argv[0]) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "%s started successfully\n", argv[0]);
} else {
stream->write_function(stream, "Failure starting %s\n", argv[0]);
}
return SWITCH_STATUS_SUCCESS;
}
if (argv[1] && !strcasecmp(argv[0], "restart") && !strcasecmp(argv[1], "all")) {
sofia_glue_restart_all_profiles();
return SWITCH_STATUS_SUCCESS;
}
if (zstr(profile_name) || !(profile = sofia_glue_find_profile(profile_name))) {
stream->write_function(stream, "Invalid Profile [%s]", switch_str_nil(profile_name));
return SWITCH_STATUS_SUCCESS;
}
if (!strcasecmp(argv[1], "killgw")) {
sofia_gateway_t *gateway_ptr;
if (argc < 3) {
stream->write_function(stream, "-ERR missing gw name\n");
goto done;
}
2010-03-31 20:02:50 +00:00
if (!strcasecmp(argv[2], "_all_")) {
sofia_glue_del_every_gateway(profile);
stream->write_function(stream, "+OK every gateway marked for deletion.\n");
} else {
2010-03-31 20:02:50 +00:00
if ((gateway_ptr = sofia_reg_find_gateway(argv[2]))) {
sofia_glue_del_gateway(gateway_ptr);
sofia_reg_release_gateway(gateway_ptr);
stream->write_function(stream, "+OK gateway marked for deletion.\n");
} else {
stream->write_function(stream, "-ERR no such gateway.\n");
}
}
goto done;
} else if (!strcasecmp(argv[1], "startgw")) {
if (argc < 3) {
stream->write_function(stream, "-ERR missing gw name\n");
goto done;
}
switch_xml_reload(&err);
stream->write_function(stream, "Reload XML [%s]\n", err);
if (config_gateway(profile->name, argv[2]) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK start gateway %s complete\n", argv[2]);
} else {
stream->write_function(stream, "-ERR cannot add gateway %s for profile %s\n", argv[2], profile->name);
}
goto done;
}
if (!strcasecmp(argv[1], "rescan")) {
2010-09-16 23:17:52 +00:00
switch_xml_reload(&err);
stream->write_function(stream, "Reload XML [%s]\n", err);
if (config_sofia(SOFIA_CONFIG_RESCAN, profile->name) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK scan complete\n");
} else {
stream->write_function(stream, "-ERR cannot find config for profile %s\n", profile->name);
}
goto done;
}
if (!strcasecmp(argv[1], "check_sync")) {
if (argc > 2) {
sofia_reg_check_call_id(profile, argv[2]);
stream->write_function(stream, "+OK syncing all registrations matching specified call_id\n");
} else {
sofia_reg_check_sync(profile);
stream->write_function(stream, "+OK syncing all registrations\n");
}
goto done;
}
if (!strcasecmp(argv[1], "flush_inbound_reg")) {
int reboot = 0;
if (argc > 2) {
if (!strcasecmp(argv[2], "reboot")) {
reboot = 1;
argc = 2;
}
}
if (argc > 2) {
if (argc > 3 && !strcasecmp(argv[3], "reboot")) {
reboot = 1;
}
sofia_reg_expire_call_id(profile, argv[2], reboot);
stream->write_function(stream, "+OK %s all registrations matching specified call_id\n", reboot ? "rebooting" : "flushing");
} else {
sofia_reg_check_expire(profile, 0, reboot);
stream->write_function(stream, "+OK %s all registrations\n", reboot ? "rebooting" : "flushing");
}
goto done;
}
2011-12-23 21:07:33 +00:00
if (!strcasecmp(argv[1], "recover")) {
if (argv[2] && !strcasecmp(argv[2], "flush")) {
sofia_glue_profile_recover(profile, SWITCH_TRUE);
2011-12-23 21:07:33 +00:00
stream->write_function(stream, "Flushing recovery database.\n");
} else {
int x = sofia_glue_profile_recover(profile, SWITCH_FALSE);
if (x) {
stream->write_function(stream, "Recovered %d session(s)\n", x);
2011-12-23 21:07:33 +00:00
} else {
stream->write_function(stream, "No sessions to recover.\n");
2011-12-23 21:07:33 +00:00
}
}
goto done;
}
if (!strcasecmp(argv[1], "register")) {
char *gname = argv[2];
sofia_gateway_t *gateway_ptr;
if (zstr(gname)) {
stream->write_function(stream, "No gateway name provided!\n");
goto done;
}
if (!strcasecmp(gname, "all")) {
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
gateway_ptr->retry = 0;
gateway_ptr->state = REG_STATE_UNREGED;
}
stream->write_function(stream, "+OK\n");
} else if ((gateway_ptr = sofia_reg_find_gateway(gname))) {
gateway_ptr->retry = 0;
gateway_ptr->state = REG_STATE_UNREGED;
stream->write_function(stream, "+OK\n");
sofia_reg_release_gateway(gateway_ptr);
} else {
stream->write_function(stream, "Invalid gateway!\n");
}
goto done;
}
if (!strcasecmp(argv[1], "unregister")) {
char *gname = argv[2];
sofia_gateway_t *gateway_ptr;
if (zstr(gname)) {
stream->write_function(stream, "No gateway name provided!\n");
goto done;
}
if (!strcasecmp(gname, "all")) {
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
gateway_ptr->retry = 0;
gateway_ptr->state = REG_STATE_UNREGISTER;
}
stream->write_function(stream, "+OK\n");
} else if ((gateway_ptr = sofia_reg_find_gateway(gname))) {
gateway_ptr->retry = 0;
gateway_ptr->state = REG_STATE_UNREGISTER;
stream->write_function(stream, "+OK\n");
sofia_reg_release_gateway(gateway_ptr);
} else {
stream->write_function(stream, "Invalid gateway!\n");
}
goto done;
}
if (!strcasecmp(argv[1], "stop") || !strcasecmp(argv[1], "restart")) {
int rsec = 10;
int diff = (int) (switch_epoch_time_now(NULL) - profile->started);
int remain = rsec - diff;
if (diff < rsec) {
stream->write_function(stream, "Profile %s must be up for at least %d seconds to stop/restart.\nPlease wait %d second%s\n",
profile->name, rsec, remain, remain == 1 ? "" : "s");
} else {
2010-09-16 23:17:52 +00:00
switch_xml_reload(&err);
stream->write_function(stream, "Reload XML [%s]\n", err);
if (!strcasecmp(argv[1], "stop")) {
sofia_clear_pflag_locked(profile, PFLAG_RUNNING);
if (argv[2] && !strcasecmp(argv[2], "wait")) {
int loops = 20 * 2;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Waiting for %s to finish SIP transactions.\n", profile->name);
while (!sofia_test_pflag(profile, PFLAG_SHUTDOWN)) {
switch_yield(500000);
if (!--loops) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Timeout Waiting for %s to finish SIP transactions.\n", profile->name);
break;
}
}
}
stream->write_function(stream, "stopping: %s", profile->name);
} else {
sofia_set_pflag_locked(profile, PFLAG_RESPAWN);
sofia_clear_pflag_locked(profile, PFLAG_RUNNING);
stream->write_function(stream, "restarting: %s", profile->name);
}
}
goto done;
}
if (!strcasecmp(argv[1], "siptrace")) {
if (argc > 2) {
int value = switch_true(argv[2]);
nua_set_params(profile->nua, TPTAG_LOG(value), TAG_END());
stream->write_function(stream, "%s sip debugging on %s", value ? "Enabled" : "Disabled", profile->name);
} else {
stream->write_function(stream, "Usage: sofia profile <name> siptrace <on/off>\n");
}
goto done;
}
if (!strcasecmp(argv[1], "capture")) {
if (argc > 2) {
int value = switch_true(argv[2]);
nua_set_params(profile->nua, TPTAG_CAPT(value ? mod_sofia_globals.capture_server : NULL), TAG_END());
stream->write_function(stream, "%s sip capturing on %s", value ? "Enabled" : "Disabled", profile->name);
} else {
stream->write_function(stream, "Usage: sofia profile <name> capture <on/off>\n");
}
goto done;
}
2011-07-31 23:36:23 +00:00
2010-10-06 20:17:48 +00:00
if (!strcasecmp(argv[1], "watchdog")) {
if (argc > 2) {
int value = switch_true(argv[2]);
profile->watchdog_enabled = value;
stream->write_function(stream, "%s sip debugging on %s", value ? "Enabled" : "Disabled", profile->name);
} else {
stream->write_function(stream, "Usage: sofia profile <name> watchdog <on/off>\n");
}
goto done;
}
if (!strcasecmp(argv[1], "gwlist")) {
int up = 1;
if (argc > 2) {
if (!strcasecmp(argv[2], "down")) {
up = 0;
}
}
sofia_glue_gateway_list(profile, stream, up);
goto done;
}
stream->write_function(stream, "-ERR Unknown command!\n");
2010-06-30 15:35:03 +00:00
done:
sofia_glue_release_profile(profile);
return SWITCH_STATUS_SUCCESS;
}
static int contact_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct cb_helper *cb = (struct cb_helper *) pArg;
char *contact;
cb->row_process++;
if (!zstr(argv[0]) && (contact = sofia_glue_get_url_from_contact(argv[0], 1))) {
if (cb->dedup) {
char *tmp = switch_mprintf("%ssofia/%s/sip:%s", argv[2], argv[1], sofia_glue_strip_proto(contact));
if (!strstr((char *)cb->stream->data, tmp)) {
cb->stream->write_function(cb->stream, "%s,", tmp);
}
2012-07-26 00:09:03 +00:00
free(tmp);
} else {
cb->stream->write_function(cb->stream, "%ssofia/%s/sip:%s,", argv[2], argv[1], sofia_glue_strip_proto(contact));
}
free(contact);
}
return 0;
}
2010-06-23 18:22:52 +00:00
SWITCH_STANDARD_API(sofia_count_reg_function)
{
char *data;
char *user = NULL;
char *domain = NULL;
char *concat = NULL;
char *profile_name = NULL;
char *p;
char *reply = "-1";
sofia_profile_t *profile = NULL;
2010-06-23 18:22:52 +00:00
if (!cmd) {
stream->write_function(stream, "%s", "");
return SWITCH_STATUS_SUCCESS;
}
data = strdup(cmd);
switch_assert(data);
if ((p = strchr(data, '/'))) {
profile_name = data;
*p++ = '\0';
user = p;
} else {
user = data;
}
if ((domain = strchr(user, '@'))) {
*domain++ = '\0';
2010-06-23 18:22:52 +00:00
if ((concat = strchr(domain, '/'))) {
*concat++ = '\0';
}
2010-06-23 18:22:52 +00:00
} else {
if ((concat = strchr(user, '/'))) {
*concat++ = '\0';
}
}
if (!profile_name && domain) {
profile_name = domain;
}
if (profile_name) {
char *sql;
if (!(profile = sofia_glue_find_profile(profile_name))) {
profile_name = domain;
domain = NULL;
}
if (!profile && profile_name) {
profile = sofia_glue_find_profile(profile_name);
}
if (profile) {
struct cb_helper_sql2str cb;
char reg_count[80] = "";
cb.buf = reg_count;
cb.len = sizeof(reg_count);
if (!domain || !strchr(domain, '.')) {
domain = profile->name;
}
if (zstr(user)) {
sql = switch_mprintf("select count(*) "
2010-06-23 18:22:52 +00:00
"from sip_registrations where (sip_host='%q' or presence_hosts like '%%%q%%')",
domain, domain);
} else {
sql = switch_mprintf("select count(*) "
"from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
user, domain, domain);
}
switch_assert(sql);
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sql2str_callback, &cb);
switch_safe_free(sql);
if (!zstr(reg_count)) {
stream->write_function(stream, "%s", reg_count);
} else {
stream->write_function(stream, "0");
}
reply = NULL;
2010-06-23 18:22:52 +00:00
}
}
if (reply) {
stream->write_function(stream, "%s", reply);
}
switch_safe_free(data);
if (profile) {
sofia_glue_release_profile(profile);
}
return SWITCH_STATUS_SUCCESS;
}
2010-06-23 18:22:52 +00:00
2011-03-25 21:35:30 +00:00
SWITCH_STANDARD_API(sofia_username_of_function)
{
char *data;
char *user = NULL;
char *domain = NULL;
char *profile_name = NULL;
char *p;
char *reply = "";
sofia_profile_t *profile = NULL;
if (!cmd) {
stream->write_function(stream, "%s", "");
return SWITCH_STATUS_SUCCESS;
}
data = strdup(cmd);
switch_assert(data);
if ((p = strchr(data, '/'))) {
profile_name = data;
*p++ = '\0';
user = p;
} else {
user = data;
}
if ((domain = strchr(user, '@'))) {
*domain++ = '\0';
}
if (!profile_name && domain) {
profile_name = domain;
}
if (profile_name) {
2011-03-25 21:35:30 +00:00
char *sql;
if (!(profile = sofia_glue_find_profile(profile_name))) {
profile_name = domain;
domain = NULL;
}
if (!profile && profile_name) {
profile = sofia_glue_find_profile(profile_name);
}
if (profile) {
struct cb_helper_sql2str cb;
char username[256] = "";
cb.buf = username;
cb.len = sizeof(username);
if (!domain || !strchr(domain, '.')) {
domain = profile->name;
}
switch_assert(!zstr(user));
sql = switch_mprintf("select sip_username "
"from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
user, domain, domain);
switch_assert(sql);
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sql2str_callback, &cb);
2011-03-25 21:35:30 +00:00
switch_safe_free(sql);
if (!zstr(username)) {
stream->write_function(stream, "%s", username);
} else {
stream->write_function(stream, "");
}
reply = NULL;
}
}
if (reply) {
stream->write_function(stream, "%s", reply);
}
switch_safe_free(data);
if (profile) {
sofia_glue_release_profile(profile);
}
return SWITCH_STATUS_SUCCESS;
}
static void select_from_profile(sofia_profile_t *profile,
const char *user,
const char *domain,
const char *concat,
const char *exclude_contact,
const char *match_user_agent,
switch_stream_handle_t *stream,
switch_bool_t dedup)
{
struct cb_helper cb;
char *sql;
char *sql_match_user_agent = NULL;
char *sql_exclude_contact = NULL;
cb.row_process = 0;
cb.profile = profile;
cb.stream = stream;
cb.dedup = dedup;
if (match_user_agent) {
sql_match_user_agent = switch_mprintf(" and user_agent like '%%%q%%'", match_user_agent);
}
if (exclude_contact) {
sql_exclude_contact = switch_mprintf(" and contact not like '%%%q%%'", exclude_contact);
}
sql = switch_mprintf("select contact, profile_name, '%q' "
"from sip_registrations where profile_name='%q' "
"and upper(sip_user)=upper('%q') "
"and (sip_host='%q' or presence_hosts like '%%%q%%')%s%s",
(concat != NULL) ? concat : "", profile->name, user, domain, domain, (sql_match_user_agent!=NULL) ? sql_match_user_agent : "", (sql_exclude_contact!=NULL) ? sql_exclude_contact : "");
switch_assert(sql);
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, contact_callback, &cb);
switch_safe_free(sql);
switch_safe_free(sql_exclude_contact);
switch_safe_free(sql_match_user_agent);
}
SWITCH_STANDARD_API(sofia_contact_function)
{
char *data;
char *user = NULL;
char *domain = NULL, *dup_domain = NULL;
char *concat = NULL;
char *profile_name = NULL;
char *p;
sofia_profile_t *profile = NULL;
const char *exclude_contact = NULL;
const char *match_user_agent = NULL;
char *reply = "error/facility_not_subscribed";
switch_stream_handle_t mystream = { 0 };
if (!cmd) {
stream->write_function(stream, "%s", "");
return SWITCH_STATUS_SUCCESS;
}
if (session) {
switch_channel_t *channel = switch_core_session_get_channel(session);
exclude_contact = switch_channel_get_variable(channel, "sip_exclude_contact");
match_user_agent = switch_channel_get_variable(channel, "sip_match_user_agent");
}
data = strdup(cmd);
switch_assert(data);
if ((p = strchr(data, '~'))) {
profile_name = data;
*p++ = '\0';
match_user_agent = p;
}
if ((p = strchr(data, '/'))) {
profile_name = data;
*p++ = '\0';
user = p;
} else {
user = data;
}
if ((domain = strchr(user, '@'))) {
*domain++ = '\0';
if ((concat = strchr(domain, '/'))) {
*concat++ = '\0';
}
} else {
if ((concat = strchr(user, '/'))) {
*concat++ = '\0';
}
}
if (zstr(domain)) {
2013-08-26 15:25:14 +00:00
dup_domain = switch_core_get_domain(SWITCH_TRUE);
domain = dup_domain;
}
if (zstr(profile_name) || strcmp(profile_name, "*") || zstr(domain)) {
if (!zstr(profile_name)) {
profile = sofia_glue_find_profile(profile_name);
}
2011-02-21 17:02:42 +00:00
if (!profile && !zstr(domain)) {
profile = sofia_glue_find_profile(domain);
}
}
if (profile || !zstr(domain)) {
SWITCH_STANDARD_STREAM(mystream);
switch_assert(mystream.data);
}
if (profile) {
if (zstr(domain)) {
domain = profile->name;
}
2010-12-29 21:04:19 +00:00
if (!zstr(profile->domain_name) && !zstr(profile_name) && !strcmp(profile_name, profile->name)) {
domain = profile->domain_name;
}
select_from_profile(profile, user, domain, concat, exclude_contact, match_user_agent, &mystream, SWITCH_FALSE);
sofia_glue_release_profile(profile);
} else if (!zstr(domain)) {
sofia_profile_t *profiles[1024] = {0};
uint8_t i = 0, j;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
if (mod_sofia_globals.profile_hash) {
switch_hash_index_t *hi;
const void *var;
void *val;
2014-04-01 22:21:29 +00:00
for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
switch_core_hash_this(hi, &var, NULL, &val);
if ((profile = (sofia_profile_t *) val) && !strcmp((char *)var, profile->name)) {
sofia_glue_profile_rdlock(profile);
profiles[i++] = profile;
profile = NULL;
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
if (i) {
for (j = 0; j < i; j++) {
select_from_profile(profiles[j], user, domain, concat, exclude_contact, match_user_agent, &mystream, SWITCH_TRUE);
sofia_glue_release_profile(profiles[j]);
}
}
}
reply = (char *) mystream.data;
if (zstr(reply)) {
reply = "error/user_not_registered";
} else if (end_of(reply) == ',') {
end_of(reply) = '\0';
}
stream->write_function(stream, "%s", reply);
reply = NULL;
switch_safe_free(mystream.data);
switch_safe_free(data);
switch_safe_free(dup_domain);
return SWITCH_STATUS_SUCCESS;
}
2013-04-17 20:38:37 +00:00
struct list_result {
int row_process;
int single_col;
switch_stream_handle_t *stream;
};
static int list_result_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct list_result *cbt = (struct list_result *) pArg;
int i = 0;
cbt->row_process++;
if (cbt->row_process == 1) {
for ( i = 0; i < argc; i++) {
cbt->stream->write_function(cbt->stream,"%s", columnNames[i]);
if (i < argc - 1) {
cbt->stream->write_function(cbt->stream,"|");
}
}
cbt->stream->write_function(cbt->stream,"\n");
}
for ( i = 0; i < argc; i++) {
cbt->stream->write_function(cbt->stream,"%s", zstr(argv[i]) ? "unknown" : argv[i]);
if (i < argc - 1) {
cbt->stream->write_function(cbt->stream,"|");
}
}
if (!cbt->single_col)
cbt->stream->write_function(cbt->stream,"\n");
return 0;
}
static void get_presence_data(sofia_profile_t *profile, const char *user, const char *domain, const char *search, switch_stream_handle_t *stream)
{
struct list_result cb;
char *sql;
char *select;
cb.row_process = 1;
cb.single_col = 1;
cb.stream = stream;
if (!strcasecmp(search, "status")) {
select = switch_mprintf(" p.status ");
} else if (!strcasecmp(search, "rpid")) {
select = switch_mprintf(" p.rpid ");
} else if (!strcasecmp(search, "user_agent")) {
select = switch_mprintf(" r.user_agent ");
} else {
cb.row_process = 0;
cb.single_col = 0;
select = switch_mprintf(" p.status, p.rpid, r.user_agent, r.network_ip, r.network_port ");
}
sql = switch_mprintf(" select %q from sip_registrations as r left join sip_presence as p "
" on p.sip_host = r.sip_host and p.profile_name = r.profile_name and p.hostname = r.orig_hostname "
" and p.sip_user = r.sip_user "
" where r.sip_realm = '%q' and r.sip_user = '%q' and r.profile_name = '%q' ", select, domain, user, profile->name);
switch_assert(sql);
sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, list_result_callback, &cb);
switch_safe_free(sql);
switch_safe_free(select);
}
/* [list|status|rpid|user_agent] [profile/]<user>@domain */
SWITCH_STANDARD_API(sofia_presence_data_function)
{
char *argv[6] = { 0 };
int argc;
char *data;
char *user = NULL;
char *domain = NULL, *dup_domain = NULL;
char *concat = NULL;
char *search = NULL;
char *profile_name = NULL;
char *p;
sofia_profile_t *profile = NULL;
if (!cmd) {
stream->write_function(stream, "%s", "");
return SWITCH_STATUS_SUCCESS;
}
data = strdup(cmd);
switch_assert(data);
argc = switch_separate_string(data, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc < 2) {
stream->write_function(stream, "%s", "");
return SWITCH_STATUS_SUCCESS;
}
search = argv[0];
if ((p = strchr(argv[1], '/'))) {
profile_name = argv[1];
*p++ = '\0';
user = p;
} else {
user = argv[1];
}
if ((domain = strchr(user, '@'))) {
*domain++ = '\0';
if ((concat = strchr(domain, '/'))) {
*concat++ = '\0';
}
} else {
if (user && (concat = strchr(user, '/'))) {
2013-04-17 20:38:37 +00:00
*concat++ = '\0';
}
}
if (zstr(domain)) {
2013-08-26 15:25:14 +00:00
dup_domain = switch_core_get_domain(SWITCH_TRUE);
2013-04-17 20:38:37 +00:00
domain = dup_domain;
}
if (!user) goto end;
if (zstr(profile_name) || strcmp(profile_name, "*") || zstr(domain)) {
if (!zstr(profile_name)) {
profile = sofia_glue_find_profile(profile_name);
}
if (!profile && !zstr(domain)) {
profile = sofia_glue_find_profile(domain);
}
}
if (profile) {
if (zstr(domain)) {
domain = profile->name;
}
if (!zstr(profile->domain_name) && !zstr(profile_name) && !strcmp(profile_name, profile->name)) {
domain = profile->domain_name;
}
get_presence_data(profile, user, domain, search, stream);
sofia_glue_release_profile(profile);
} else if (!zstr(domain)) {
switch_mutex_lock(mod_sofia_globals.hash_mutex);
if (mod_sofia_globals.profile_hash) {
switch_hash_index_t *hi;
const void *var;
void *val;
2014-04-01 22:21:29 +00:00
for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
switch_core_hash_this(hi, &var, NULL, &val);
2013-04-17 20:38:37 +00:00
if ((profile = (sofia_profile_t *) val) && !strcmp((char *)var, profile->name)) {
get_presence_data(profile, user, domain, search, stream);
profile = NULL;
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
if (!strcasecmp(search, "list"))
stream->write_function(stream, "+OK\n");
end:
switch_safe_free(data);
switch_safe_free(dup_domain);
return SWITCH_STATUS_SUCCESS;
}
/* <gateway_name> [ivar|ovar|var] <name> */
SWITCH_STANDARD_API(sofia_gateway_data_function)
{
char *argv[4];
char *mydata;
int argc;
sofia_gateway_t *gateway;
char *gwname, *param, *varname;
const char *val = NULL;
if (zstr(cmd)) {
stream->write_function(stream, "-ERR Parameter missing\n");
return SWITCH_STATUS_SUCCESS;
}
if (!(mydata = strdup(cmd))) {
return SWITCH_STATUS_FALSE;
}
if (!(argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || !argv[0]) {
goto end;
}
gwname = argv[0];
param = argv[1];
varname = argv[2];
if (zstr(gwname) || zstr(param) || zstr(varname)) {
goto end;
}
if (!(gateway = sofia_reg_find_gateway(gwname))) {
goto end;
}
if (!strcasecmp(param, "ivar") && gateway->ib_vars && (val = switch_event_get_header(gateway->ib_vars, varname))) {
stream->write_function(stream, "%s", val);
} else if (!strcasecmp(param, "ovar") && gateway->ob_vars && (val = switch_event_get_header(gateway->ob_vars, varname))) {
stream->write_function(stream, "%s", val);
} else if (!strcasecmp(param, "var")) {
if (gateway->ib_vars && (val = switch_event_get_header(gateway->ib_vars, varname))) {
stream->write_function(stream, "%s", val);
} else if (gateway->ob_vars && (val = switch_event_get_header(gateway->ob_vars, varname))) {
stream->write_function(stream, "%s", val);
}
}
sofia_reg_release_gateway(gateway);
2010-06-30 15:35:03 +00:00
end:
switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(sofia_function)
{
char *argv[1024] = { 0 };
int argc = 0;
char *mycmd = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
sofia_command_t func = NULL;
int lead = 1;
static const char usage_string[] = "USAGE:\n"
"--------------------------------------------------------------------------------\n"
"sofia global siptrace <on|off>\n"
2011-07-31 23:36:23 +00:00
"sofia capture <on|off>\n"
" watchdog <on|off>\n\n"
"sofia profile <name> [start | stop | restart | rescan] [wait]\n"
" flush_inbound_reg [<call_id> | <[user]@domain>] [reboot]\n"
" check_sync [<call_id> | <[user]@domain>]\n"
" [register | unregister] [<gateway name> | all]\n"
" killgw <gateway name>\n"
" [stun-auto-disable | stun-enabled] [true | false]]\n"
" siptrace <on|off>\n"
2011-07-31 23:36:23 +00:00
" capture <on|off>\n"
" watchdog <on|off>\n\n"
2011-11-17 22:25:50 +00:00
"sofia <status|xmlstatus> profile <name> [reg [<contact str>]] | [pres <pres str>] | [user <user@domain>]\n"
"sofia <status|xmlstatus> gateway <name>\n\n"
"sofia loglevel <all|default|tport|iptsec|nea|nta|nth_client|nth_server|nua|soa|sresolv|stun> [0-9]\n"
"sofia tracelevel <console|alert|crit|err|warning|notice|info|debug>\n\n"
"sofia help\n"
"--------------------------------------------------------------------------------\n";
if (zstr(cmd)) {
stream->write_function(stream, "%s", usage_string);
goto done;
}
if (!(mycmd = strdup(cmd))) {
status = SWITCH_STATUS_MEMERR;
goto done;
}
if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || !argv[0]) {
stream->write_function(stream, "%s", usage_string);
goto done;
}
if (!strcasecmp(argv[0], "profile")) {
func = cmd_profile;
} else if (!strcasecmp(argv[0], "status")) {
func = cmd_status;
} else if (!strcasecmp(argv[0], "xmlstatus")) {
func = cmd_xml_status;
} else if (!strcasecmp(argv[0], "jsonstatus")) {
func = cmd_json_status;
} else if (!strcasecmp(argv[0], "tracelevel")) {
if (argv[1]) {
mod_sofia_globals.tracelevel = switch_log_str2level(argv[1]);
}
stream->write_function(stream, "+OK tracelevel is %s", switch_log_level2str(mod_sofia_globals.tracelevel));
goto done;
} else if (!strcasecmp(argv[0], "loglevel")) {
if (argc > 2 && argv[2] && switch_is_number(argv[2])) {
int level = atoi(argv[2]);
if (sofia_set_loglevel(argv[1], level) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "Sofia log level for component [%s] has been set to [%d]", argv[1], level);
} else {
stream->write_function(stream, "%s", usage_string);
}
} else if (argc > 1 && argv[1]) {
int level = sofia_get_loglevel(argv[1]);
if (level >= 0) {
stream->write_function(stream, "Sofia-sip loglevel for [%s] is [%d]", argv[1], level);
} else {
stream->write_function(stream, "%s", usage_string);
}
} else {
stream->write_function(stream, "%s", usage_string);
}
goto done;
} else if (!strcasecmp(argv[0], "help")) {
stream->write_function(stream, "%s", usage_string);
goto done;
} else if (!strcasecmp(argv[0], "global")) {
2010-10-06 20:17:48 +00:00
int ston = -1;
2011-07-31 23:36:23 +00:00
int cton = -1;
2010-10-06 20:17:48 +00:00
int wdon = -1;
int stbyon = -1;
if (argc > 1) {
if (!strcasecmp(argv[1], "debug")) {
if (argc > 2) {
if (strstr(argv[2], "presence")) {
2011-02-07 20:35:56 +00:00
mod_sofia_globals.debug_presence = 10;
stream->write_function(stream, "+OK Debugging presence\n");
}
if (strstr(argv[2], "sla")) {
2012-01-26 10:46:48 +00:00
mod_sofia_globals.debug_sla = 10;
stream->write_function(stream, "+OK Debugging sla\n");
}
if (strstr(argv[2], "none")) {
stream->write_function(stream, "+OK Debugging nothing\n");
mod_sofia_globals.debug_presence = 0;
mod_sofia_globals.debug_sla = 0;
}
}
stream->write_function(stream, "+OK Debugging summary: presence: %s sla: %s\n",
mod_sofia_globals.debug_presence ? "on" : "off",
mod_sofia_globals.debug_sla ? "on" : "off");
goto done;
}
if (!strcasecmp(argv[1], "siptrace")) {
if (argc > 2) {
2010-10-06 20:17:48 +00:00
ston = switch_true(argv[2]);
}
}
if (!strcasecmp(argv[1], "standby")) {
if (argc > 2) {
stbyon = switch_true(argv[2]);
}
}
2011-07-31 23:36:23 +00:00
if (!strcasecmp(argv[1], "capture")) {
if (argc > 2) {
cton = switch_true(argv[2]);
}
}
2011-07-31 23:36:23 +00:00
2010-10-06 20:17:48 +00:00
if (!strcasecmp(argv[1], "watchdog")) {
if (argc > 2) {
wdon = switch_true(argv[2]);
}
}
}
2010-10-06 20:17:48 +00:00
if (ston != -1) {
sofia_glue_global_siptrace(ston);
stream->write_function(stream, "+OK Global siptrace %s", ston ? "on" : "off");
2011-07-31 23:36:23 +00:00
} else if (cton != -1) {
sofia_glue_global_capture(cton);
stream->write_function(stream, "+OK Global capture %s", cton ? "on" : "off");
2010-10-06 20:17:48 +00:00
} else if (wdon != -1) {
sofia_glue_global_watchdog(wdon);
stream->write_function(stream, "+OK Global watchdog %s", wdon ? "on" : "off");
} else if (stbyon != -1) {
sofia_glue_global_standby(stbyon);
stream->write_function(stream, "+OK Global standby %s", stbyon ? "on" : "off");
} else {
2011-07-31 23:36:23 +00:00
stream->write_function(stream, "-ERR Usage: siptrace <on|off>|capture <on|off>|watchdog <on|off>|debug <sla|presence|none");
}
goto done;
} else if (!strcasecmp(argv[0], "recover")) {
if (argv[1] && !strcasecmp(argv[1], "flush")) {
sofia_glue_recover(SWITCH_TRUE);
stream->write_function(stream, "Flushing recovery database.\n");
} else {
2010-08-26 18:50:50 +00:00
int x = sofia_glue_recover(SWITCH_FALSE);
2011-12-15 02:56:00 +00:00
switch_event_t *event = NULL;
2010-08-18 20:33:18 +00:00
if (x) {
2011-12-15 02:56:00 +00:00
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM,
MY_EVENT_RECOVERY_RECOVERED) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "recovered_calls", "%d", x);
switch_event_fire(&event);
}
stream->write_function(stream, "Recovered %d call(s)\n", x);
} else {
2011-12-15 02:56:00 +00:00
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM,
MY_EVENT_RECOVERY_RECOVERED) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "recovered_calls", "0");
switch_event_fire(&event);
}
stream->write_function(stream, "No calls to recover.\n");
}
}
goto done;
}
if (func) {
status = func(&argv[lead], argc - lead, stream);
} else {
stream->write_function(stream, "Unknown Command [%s]\n", argv[0]);
}
2010-06-30 15:35:03 +00:00
done:
switch_safe_free(mycmd);
return status;
}
switch_io_routines_t sofia_io_routines = {
/*.outgoing_channel */ sofia_outgoing_channel,
/*.read_frame */ sofia_read_frame,
/*.write_frame */ sofia_write_frame,
/*.kill_channel */ sofia_kill_channel,
/*.send_dtmf */ sofia_send_dtmf,
/*.receive_message */ sofia_receive_message,
/*.receive_event */ sofia_receive_event,
/*.state_change */ NULL,
/*.read_video_frame */ sofia_read_video_frame,
/*.write_video_frame */ sofia_write_video_frame,
2016-07-11 03:25:14 +00:00
/*.read_text_frame */ sofia_read_text_frame,
/*.write_text_frame */ sofia_write_text_frame,
/*.state_run*/ NULL,
/*.get_jb*/ sofia_get_jb
};
switch_state_handler_table_t sofia_event_handlers = {
/*.on_init */ sofia_on_init,
/*.on_routing */ sofia_on_routing,
/*.on_execute */ sofia_on_execute,
/*.on_hangup */ sofia_on_hangup,
/*.on_exchange_media */ sofia_on_exchange_media,
/*.on_soft_execute */ sofia_on_soft_execute,
/*.on_consume_media */ NULL,
/*.on_hibernate */ sofia_on_hibernate,
/*.on_reset */ sofia_on_reset,
/*.on_park */ NULL,
/*.on_reporting */ NULL,
/*.on_destroy */ sofia_on_destroy
};
static switch_status_t sofia_manage(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen)
{
return SWITCH_STATUS_SUCCESS;
}
Presence and Chat Gateway Code This is some brand new stuff to gateway chat/presence/audio from one protocol to another So far it only works between google/jingle and SIP All I had to test the SIP end was X-Lite and Eyebeam and GoogleTalk on the jingle end. With this setup registered X-Lite's can chat with each other and call each other as well as X-Lite to GoogleTalk and GoogleTalk to X-Lite audio calls. Chat May also be done between X-Lite and jabber You'll also need a jabber server configured for component login so you can interface. We have only tested with jabberd2 so far. Configure DNS so srv records for jabber for your subdomain (fs.mydomain.com in the example) so the jabber records are pointed at your jabber server. RELEVANT CONFIGS <!-- Brian has no jingle support so send calls to him over to his iax url --> <extension name="bkw"> <condition field="destination_number" expression="^jingle\+brian@agents.cylynx.com$"> <action application="bridge" data="iax/guest@brianwest.homeunix.org/9184290404"/> </condition> </extension> <!-- Assumption is made here that both sip and jingle have the same profile/domain name as documented below --> <extension name="jingle2sip"> <condition field="source" expression="mod_dingaling"/> <condition field="destination_number" expression="^sip\+([^\@]+)\@(.*)$"> <action application="bridge" data="sofia/$2/$1%$2"/> </condition> </extension> <extension name="sip2jingle"> <condition field="source" expression="mod_sofia"/> <condition field="destination_number" expression="^jingle\+([^\@]+)\@(.*)$"> <action application="bridge" data="dingaling/sip+${sip_fromuser}@${sip_fromhost}/$1@$2"/> </condition> </extension> <configuration name="sofia.conf" description="sofia Endpoint"> <global_settings> <param name="log-level" value="0"/> </global_settings> <profiles> <profile name="fs.mydomain.com"> <registrations/> <settings> <param name="debug" value="1"/> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="codec-ms" value="20"/> <param name="accept-blind-reg" value="true"/> <param name="manage-presence" value="true"/> <!--<param name="full-id-in-dialplan" value="true"/>--> <!--<param name="auth-calls" value="true"/>--> <!--<param name="auth-all-packets" value="true"/>--> <param name="use-rtp-timer" value="true"/> <param name="rtp-timer-name" value="soft"/> <param name="rtp-ip" value="100.200.100.200"/> <param name="sip-ip" value="fs.mydomain.com"/> </settings> </profile> </profiles> </configuration> <configuration name="dingaling.conf" description="XMPP Jingle Endpoint"> <settings> <param name="debug" value="0"/> <param name="codec-prefs" value="PCMU"/> </settings> <profile type="component"> <param name="name" value="fs.mydomain.com"/> <param name="password" value="secret"/> <param name="dialplan" value="XML"/> <param name="rtp-ip" value="208.64.200.42"/> <param name="server" value="jabber.freeswitch.org:5347"/> <!-- disable to trade async for more calls --> <param name="use-rtp-timer" value="true"/> <param name="exten" value="_auto_"/> <!--<param name="vad" value="both"/>--> </profile> </configuration> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3115 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-10-20 06:17:00 +00:00
2015-01-26 17:01:40 +00:00
static int protect_dest_uri(switch_caller_profile_t *cp)
2015-01-23 21:06:16 +00:00
{
char *p = cp->destination_number, *o = p;
char *q = NULL, *e = NULL, *qenc = NULL;
switch_size_t enclen = 0;
2015-01-26 17:01:40 +00:00
int mod = 0;
2015-01-23 21:06:16 +00:00
if (!(e = strchr(p, '@'))) {
return 0;
}
2015-01-23 21:06:16 +00:00
while((p = strchr(p, '/'))) {
q = p++;
}
if (q) {
const char *i;
int go = 0;
for (i = q+1; i && *i && *i != '@'; i++) {
if (strchr(SWITCH_URL_UNSAFE, *i)) {
go = 1;
}
}
2015-01-26 17:01:40 +00:00
if (!go) return 0;
2015-01-23 21:06:16 +00:00
*q++ = '\0';
} else {
2015-01-26 17:01:40 +00:00
return 0;
2015-01-23 21:06:16 +00:00
}
2015-01-23 21:06:16 +00:00
if (!strncasecmp(q, "sips:", 5)) {
q += 5;
} else if (!strncasecmp(q, "sip:", 4)) {
q += 4;
}
if (!(e = strchr(q, '@'))) {
2015-01-26 17:01:40 +00:00
return 0;
2015-01-23 21:06:16 +00:00
}
*e++ = '\0';
if (switch_needs_url_encode(q)) {
2018-11-02 01:31:05 +00:00
enclen = (strlen(q) * 3) + 2;
2015-01-23 21:06:16 +00:00
qenc = switch_core_alloc(cp->pool, enclen);
switch_url_encode(q, qenc, enclen);
2015-01-26 17:01:40 +00:00
mod = 1;
2015-01-23 21:06:16 +00:00
}
2015-01-23 21:06:16 +00:00
cp->destination_number = switch_core_sprintf(cp->pool, "%s/%s@%s", o, qenc ? qenc : q, e);
2015-01-26 17:01:40 +00:00
return mod;
2015-01-23 21:06:16 +00:00
}
static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session,
switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
{
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
switch_core_session_t *nsession = NULL;
char *data, *profile_name, *dest; //, *dest_num = NULL;
sofia_profile_t *profile = NULL;
switch_caller_profile_t *caller_profile = NULL;
private_object_t *tech_pvt = NULL;
switch_channel_t *nchannel;
char *host = NULL, *dest_to = NULL;
const char *hval = NULL;
char *not_const = NULL;
2010-06-05 00:37:04 +00:00
int cid_locked = 0;
switch_channel_t *o_channel = NULL;
2011-06-07 02:28:14 +00:00
sofia_gateway_t *gateway_ptr = NULL;
2015-01-26 17:01:40 +00:00
int mod = 0;
*new_session = NULL;
Presence and Chat Gateway Code This is some brand new stuff to gateway chat/presence/audio from one protocol to another So far it only works between google/jingle and SIP All I had to test the SIP end was X-Lite and Eyebeam and GoogleTalk on the jingle end. With this setup registered X-Lite's can chat with each other and call each other as well as X-Lite to GoogleTalk and GoogleTalk to X-Lite audio calls. Chat May also be done between X-Lite and jabber You'll also need a jabber server configured for component login so you can interface. We have only tested with jabberd2 so far. Configure DNS so srv records for jabber for your subdomain (fs.mydomain.com in the example) so the jabber records are pointed at your jabber server. RELEVANT CONFIGS <!-- Brian has no jingle support so send calls to him over to his iax url --> <extension name="bkw"> <condition field="destination_number" expression="^jingle\+brian@agents.cylynx.com$"> <action application="bridge" data="iax/guest@brianwest.homeunix.org/9184290404"/> </condition> </extension> <!-- Assumption is made here that both sip and jingle have the same profile/domain name as documented below --> <extension name="jingle2sip"> <condition field="source" expression="mod_dingaling"/> <condition field="destination_number" expression="^sip\+([^\@]+)\@(.*)$"> <action application="bridge" data="sofia/$2/$1%$2"/> </condition> </extension> <extension name="sip2jingle"> <condition field="source" expression="mod_sofia"/> <condition field="destination_number" expression="^jingle\+([^\@]+)\@(.*)$"> <action application="bridge" data="dingaling/sip+${sip_fromuser}@${sip_fromhost}/$1@$2"/> </condition> </extension> <configuration name="sofia.conf" description="sofia Endpoint"> <global_settings> <param name="log-level" value="0"/> </global_settings> <profiles> <profile name="fs.mydomain.com"> <registrations/> <settings> <param name="debug" value="1"/> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="codec-ms" value="20"/> <param name="accept-blind-reg" value="true"/> <param name="manage-presence" value="true"/> <!--<param name="full-id-in-dialplan" value="true"/>--> <!--<param name="auth-calls" value="true"/>--> <!--<param name="auth-all-packets" value="true"/>--> <param name="use-rtp-timer" value="true"/> <param name="rtp-timer-name" value="soft"/> <param name="rtp-ip" value="100.200.100.200"/> <param name="sip-ip" value="fs.mydomain.com"/> </settings> </profile> </profiles> </configuration> <configuration name="dingaling.conf" description="XMPP Jingle Endpoint"> <settings> <param name="debug" value="0"/> <param name="codec-prefs" value="PCMU"/> </settings> <profile type="component"> <param name="name" value="fs.mydomain.com"/> <param name="password" value="secret"/> <param name="dialplan" value="XML"/> <param name="rtp-ip" value="208.64.200.42"/> <param name="server" value="jabber.freeswitch.org:5347"/> <!-- disable to trade async for more calls --> <param name="use-rtp-timer" value="true"/> <param name="exten" value="_auto_"/> <!--<param name="vad" value="both"/>--> </profile> </configuration> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3115 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-10-20 06:17:00 +00:00
if (!outbound_profile || zstr(outbound_profile->destination_number)) {
2011-12-15 17:16:41 +00:00
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid Empty Destination\n");
goto error;
}
2015-01-23 21:06:16 +00:00
if (!switch_true(switch_event_get_header(var_event, "sofia_suppress_url_encoding"))) {
2015-01-26 17:01:40 +00:00
mod = protect_dest_uri(outbound_profile);
2015-01-23 21:06:16 +00:00
}
if (!(nsession = switch_core_session_request_uuid(sofia_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND,
flags, pool, switch_event_get_header(var_event, "origination_uuid")))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Creating Session\n");
goto error;
}
Presence and Chat Gateway Code This is some brand new stuff to gateway chat/presence/audio from one protocol to another So far it only works between google/jingle and SIP All I had to test the SIP end was X-Lite and Eyebeam and GoogleTalk on the jingle end. With this setup registered X-Lite's can chat with each other and call each other as well as X-Lite to GoogleTalk and GoogleTalk to X-Lite audio calls. Chat May also be done between X-Lite and jabber You'll also need a jabber server configured for component login so you can interface. We have only tested with jabberd2 so far. Configure DNS so srv records for jabber for your subdomain (fs.mydomain.com in the example) so the jabber records are pointed at your jabber server. RELEVANT CONFIGS <!-- Brian has no jingle support so send calls to him over to his iax url --> <extension name="bkw"> <condition field="destination_number" expression="^jingle\+brian@agents.cylynx.com$"> <action application="bridge" data="iax/guest@brianwest.homeunix.org/9184290404"/> </condition> </extension> <!-- Assumption is made here that both sip and jingle have the same profile/domain name as documented below --> <extension name="jingle2sip"> <condition field="source" expression="mod_dingaling"/> <condition field="destination_number" expression="^sip\+([^\@]+)\@(.*)$"> <action application="bridge" data="sofia/$2/$1%$2"/> </condition> </extension> <extension name="sip2jingle"> <condition field="source" expression="mod_sofia"/> <condition field="destination_number" expression="^jingle\+([^\@]+)\@(.*)$"> <action application="bridge" data="dingaling/sip+${sip_fromuser}@${sip_fromhost}/$1@$2"/> </condition> </extension> <configuration name="sofia.conf" description="sofia Endpoint"> <global_settings> <param name="log-level" value="0"/> </global_settings> <profiles> <profile name="fs.mydomain.com"> <registrations/> <settings> <param name="debug" value="1"/> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="codec-ms" value="20"/> <param name="accept-blind-reg" value="true"/> <param name="manage-presence" value="true"/> <!--<param name="full-id-in-dialplan" value="true"/>--> <!--<param name="auth-calls" value="true"/>--> <!--<param name="auth-all-packets" value="true"/>--> <param name="use-rtp-timer" value="true"/> <param name="rtp-timer-name" value="soft"/> <param name="rtp-ip" value="100.200.100.200"/> <param name="sip-ip" value="fs.mydomain.com"/> </settings> </profile> </profiles> </configuration> <configuration name="dingaling.conf" description="XMPP Jingle Endpoint"> <settings> <param name="debug" value="0"/> <param name="codec-prefs" value="PCMU"/> </settings> <profile type="component"> <param name="name" value="fs.mydomain.com"/> <param name="password" value="secret"/> <param name="dialplan" value="XML"/> <param name="rtp-ip" value="208.64.200.42"/> <param name="server" value="jabber.freeswitch.org:5347"/> <!-- disable to trade async for more calls --> <param name="use-rtp-timer" value="true"/> <param name="exten" value="_auto_"/> <!--<param name="vad" value="both"/>--> </profile> </configuration> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3115 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-10-20 06:17:00 +00:00
tech_pvt = sofia_glue_new_pvt(nsession);
data = switch_core_session_strdup(nsession, outbound_profile->destination_number);
if ((dest_to = strchr(data, '^'))) {
*dest_to++ = '\0';
}
profile_name = data;
nchannel = switch_core_session_get_channel(nsession);
if (session) {
o_channel = switch_core_session_get_channel(session);
}
if ((hval = switch_event_get_header(var_event, "sip_invite_to_uri"))) {
dest_to = switch_core_session_strdup(nsession, hval);
}
if (!strncasecmp(profile_name, "gateway/", 8)) {
char *gw, *params;
Presence and Chat Gateway Code This is some brand new stuff to gateway chat/presence/audio from one protocol to another So far it only works between google/jingle and SIP All I had to test the SIP end was X-Lite and Eyebeam and GoogleTalk on the jingle end. With this setup registered X-Lite's can chat with each other and call each other as well as X-Lite to GoogleTalk and GoogleTalk to X-Lite audio calls. Chat May also be done between X-Lite and jabber You'll also need a jabber server configured for component login so you can interface. We have only tested with jabberd2 so far. Configure DNS so srv records for jabber for your subdomain (fs.mydomain.com in the example) so the jabber records are pointed at your jabber server. RELEVANT CONFIGS <!-- Brian has no jingle support so send calls to him over to his iax url --> <extension name="bkw"> <condition field="destination_number" expression="^jingle\+brian@agents.cylynx.com$"> <action application="bridge" data="iax/guest@brianwest.homeunix.org/9184290404"/> </condition> </extension> <!-- Assumption is made here that both sip and jingle have the same profile/domain name as documented below --> <extension name="jingle2sip"> <condition field="source" expression="mod_dingaling"/> <condition field="destination_number" expression="^sip\+([^\@]+)\@(.*)$"> <action application="bridge" data="sofia/$2/$1%$2"/> </condition> </extension> <extension name="sip2jingle"> <condition field="source" expression="mod_sofia"/> <condition field="destination_number" expression="^jingle\+([^\@]+)\@(.*)$"> <action application="bridge" data="dingaling/sip+${sip_fromuser}@${sip_fromhost}/$1@$2"/> </condition> </extension> <configuration name="sofia.conf" description="sofia Endpoint"> <global_settings> <param name="log-level" value="0"/> </global_settings> <profiles> <profile name="fs.mydomain.com"> <registrations/> <settings> <param name="debug" value="1"/> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="codec-ms" value="20"/> <param name="accept-blind-reg" value="true"/> <param name="manage-presence" value="true"/> <!--<param name="full-id-in-dialplan" value="true"/>--> <!--<param name="auth-calls" value="true"/>--> <!--<param name="auth-all-packets" value="true"/>--> <param name="use-rtp-timer" value="true"/> <param name="rtp-timer-name" value="soft"/> <param name="rtp-ip" value="100.200.100.200"/> <param name="sip-ip" value="fs.mydomain.com"/> </settings> </profile> </profiles> </configuration> <configuration name="dingaling.conf" description="XMPP Jingle Endpoint"> <settings> <param name="debug" value="0"/> <param name="codec-prefs" value="PCMU"/> </settings> <profile type="component"> <param name="name" value="fs.mydomain.com"/> <param name="password" value="secret"/> <param name="dialplan" value="XML"/> <param name="rtp-ip" value="208.64.200.42"/> <param name="server" value="jabber.freeswitch.org:5347"/> <!-- disable to trade async for more calls --> <param name="use-rtp-timer" value="true"/> <param name="exten" value="_auto_"/> <!--<param name="vad" value="both"/>--> </profile> </configuration> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3115 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-10-20 06:17:00 +00:00
if (!(gw = strchr(profile_name, '/'))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL \'%s\'\n", profile_name);
2011-12-15 17:16:41 +00:00
cause = SWITCH_CAUSE_INVALID_URL;
goto error;
}
*gw++ = '\0';
if (!(dest = strchr(gw, '/'))) {
2011-12-15 17:16:41 +00:00
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL \'%s\'\n", gw);
cause = SWITCH_CAUSE_INVALID_URL;
goto error;
}
*dest++ = '\0';
if (!(gateway_ptr = sofia_reg_find_gateway(gw))) {
2011-12-15 17:16:41 +00:00
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Gateway \'%s\'\n", gw);
cause = SWITCH_CAUSE_INVALID_GATEWAY;
goto error;
}
if (gateway_ptr->status != SOFIA_GATEWAY_UP) {
2011-12-15 17:16:41 +00:00
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Gateway \'%s\' is down!\n", gw);
cause = SWITCH_CAUSE_GATEWAY_DOWN;
gateway_ptr->ob_failed_calls++;
goto error;
}
tech_pvt->transport = gateway_ptr->register_transport;
2010-06-05 00:37:04 +00:00
tech_pvt->cid_type = gateway_ptr->cid_type;
cid_locked = 1;
/*
* Handle params, strip them off the destination and add them to the
* invite contact.
*
*/
2013-02-26 22:37:29 +00:00
2013-02-27 15:04:51 +00:00
if ((params = strchr(dest, ';'))) {
char *tp_param;
*params++ = '\0';
if ((tp_param = (char *) switch_stristr("port=", params))) {
tp_param += 5;
tech_pvt->transport = sofia_glue_str2transport(tp_param);
if (tech_pvt->transport == SOFIA_TRANSPORT_UNKNOWN) {
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
gateway_ptr->ob_failed_calls++;
goto error;
}
}
}
if (tech_pvt->transport != gateway_ptr->register_transport) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
"You are trying to use a different transport type for this gateway (overriding the register-transport), this is unsupported!\n");
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
goto error;
}
profile = gateway_ptr->profile;
2011-12-16 20:41:48 +00:00
if (profile && sofia_test_pflag(profile, PFLAG_STANDBY)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "System Paused\n");
cause = SWITCH_CAUSE_SYSTEM_SHUTDOWN;
goto error;
}
tech_pvt->gateway_name = switch_core_session_strdup(nsession, gateway_ptr->name);
switch_channel_set_variable(nchannel, "sip_gateway_name", gateway_ptr->name);
if (!sofia_test_flag(gateway_ptr, REG_FLAG_CALLERID)) {
tech_pvt->gateway_from_str = switch_core_session_strdup(nsession, gateway_ptr->register_from);
}
if (!strchr(dest, '@')) {
tech_pvt->dest = switch_core_session_sprintf(nsession, "sip:%s%s@%s", gateway_ptr->destination_prefix, dest, sofia_glue_strip_proto(gateway_ptr->register_proxy));
Presence and Chat Gateway Code This is some brand new stuff to gateway chat/presence/audio from one protocol to another So far it only works between google/jingle and SIP All I had to test the SIP end was X-Lite and Eyebeam and GoogleTalk on the jingle end. With this setup registered X-Lite's can chat with each other and call each other as well as X-Lite to GoogleTalk and GoogleTalk to X-Lite audio calls. Chat May also be done between X-Lite and jabber You'll also need a jabber server configured for component login so you can interface. We have only tested with jabberd2 so far. Configure DNS so srv records for jabber for your subdomain (fs.mydomain.com in the example) so the jabber records are pointed at your jabber server. RELEVANT CONFIGS <!-- Brian has no jingle support so send calls to him over to his iax url --> <extension name="bkw"> <condition field="destination_number" expression="^jingle\+brian@agents.cylynx.com$"> <action application="bridge" data="iax/guest@brianwest.homeunix.org/9184290404"/> </condition> </extension> <!-- Assumption is made here that both sip and jingle have the same profile/domain name as documented below --> <extension name="jingle2sip"> <condition field="source" expression="mod_dingaling"/> <condition field="destination_number" expression="^sip\+([^\@]+)\@(.*)$"> <action application="bridge" data="sofia/$2/$1%$2"/> </condition> </extension> <extension name="sip2jingle"> <condition field="source" expression="mod_sofia"/> <condition field="destination_number" expression="^jingle\+([^\@]+)\@(.*)$"> <action application="bridge" data="dingaling/sip+${sip_fromuser}@${sip_fromhost}/$1@$2"/> </condition> </extension> <configuration name="sofia.conf" description="sofia Endpoint"> <global_settings> <param name="log-level" value="0"/> </global_settings> <profiles> <profile name="fs.mydomain.com"> <registrations/> <settings> <param name="debug" value="1"/> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="codec-ms" value="20"/> <param name="accept-blind-reg" value="true"/> <param name="manage-presence" value="true"/> <!--<param name="full-id-in-dialplan" value="true"/>--> <!--<param name="auth-calls" value="true"/>--> <!--<param name="auth-all-packets" value="true"/>--> <param name="use-rtp-timer" value="true"/> <param name="rtp-timer-name" value="soft"/> <param name="rtp-ip" value="100.200.100.200"/> <param name="sip-ip" value="fs.mydomain.com"/> </settings> </profile> </profiles> </configuration> <configuration name="dingaling.conf" description="XMPP Jingle Endpoint"> <settings> <param name="debug" value="0"/> <param name="codec-prefs" value="PCMU"/> </settings> <profile type="component"> <param name="name" value="fs.mydomain.com"/> <param name="password" value="secret"/> <param name="dialplan" value="XML"/> <param name="rtp-ip" value="208.64.200.42"/> <param name="server" value="jabber.freeswitch.org:5347"/> <!-- disable to trade async for more calls --> <param name="use-rtp-timer" value="true"/> <param name="exten" value="_auto_"/> <!--<param name="vad" value="both"/>--> </profile> </configuration> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3115 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-10-20 06:17:00 +00:00
} else {
tech_pvt->dest = switch_core_session_sprintf(nsession, "sip:%s%s", gateway_ptr->destination_prefix, dest);
Presence and Chat Gateway Code This is some brand new stuff to gateway chat/presence/audio from one protocol to another So far it only works between google/jingle and SIP All I had to test the SIP end was X-Lite and Eyebeam and GoogleTalk on the jingle end. With this setup registered X-Lite's can chat with each other and call each other as well as X-Lite to GoogleTalk and GoogleTalk to X-Lite audio calls. Chat May also be done between X-Lite and jabber You'll also need a jabber server configured for component login so you can interface. We have only tested with jabberd2 so far. Configure DNS so srv records for jabber for your subdomain (fs.mydomain.com in the example) so the jabber records are pointed at your jabber server. RELEVANT CONFIGS <!-- Brian has no jingle support so send calls to him over to his iax url --> <extension name="bkw"> <condition field="destination_number" expression="^jingle\+brian@agents.cylynx.com$"> <action application="bridge" data="iax/guest@brianwest.homeunix.org/9184290404"/> </condition> </extension> <!-- Assumption is made here that both sip and jingle have the same profile/domain name as documented below --> <extension name="jingle2sip"> <condition field="source" expression="mod_dingaling"/> <condition field="destination_number" expression="^sip\+([^\@]+)\@(.*)$"> <action application="bridge" data="sofia/$2/$1%$2"/> </condition> </extension> <extension name="sip2jingle"> <condition field="source" expression="mod_sofia"/> <condition field="destination_number" expression="^jingle\+([^\@]+)\@(.*)$"> <action application="bridge" data="dingaling/sip+${sip_fromuser}@${sip_fromhost}/$1@$2"/> </condition> </extension> <configuration name="sofia.conf" description="sofia Endpoint"> <global_settings> <param name="log-level" value="0"/> </global_settings> <profiles> <profile name="fs.mydomain.com"> <registrations/> <settings> <param name="debug" value="1"/> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="codec-ms" value="20"/> <param name="accept-blind-reg" value="true"/> <param name="manage-presence" value="true"/> <!--<param name="full-id-in-dialplan" value="true"/>--> <!--<param name="auth-calls" value="true"/>--> <!--<param name="auth-all-packets" value="true"/>--> <param name="use-rtp-timer" value="true"/> <param name="rtp-timer-name" value="soft"/> <param name="rtp-ip" value="100.200.100.200"/> <param name="sip-ip" value="fs.mydomain.com"/> </settings> </profile> </profiles> </configuration> <configuration name="dingaling.conf" description="XMPP Jingle Endpoint"> <settings> <param name="debug" value="0"/> <param name="codec-prefs" value="PCMU"/> </settings> <profile type="component"> <param name="name" value="fs.mydomain.com"/> <param name="password" value="secret"/> <param name="dialplan" value="XML"/> <param name="rtp-ip" value="208.64.200.42"/> <param name="server" value="jabber.freeswitch.org:5347"/> <!-- disable to trade async for more calls --> <param name="use-rtp-timer" value="true"/> <param name="exten" value="_auto_"/> <!--<param name="vad" value="both"/>--> </profile> </configuration> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3115 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-10-20 06:17:00 +00:00
}
if ((host = switch_core_session_strdup(nsession, tech_pvt->dest))) {
char *pp = strchr(host, '@');
if (pp) {
host = pp + 1;
} else {
host = NULL;
dest_to = NULL;
}
}
if (params) {
tech_pvt->invite_contact = switch_core_session_sprintf(nsession, "%s;%s", gateway_ptr->register_contact, params);
tech_pvt->dest = switch_core_session_sprintf(nsession, "%s;%s", tech_pvt->dest, params);
} else {
tech_pvt->invite_contact = switch_core_session_strdup(nsession, gateway_ptr->register_contact);
}
gateway_ptr->ob_calls++;
if (!zstr(gateway_ptr->from_domain) && !switch_channel_get_variable(nchannel, "sip_invite_domain")) {
if (!strcasecmp(gateway_ptr->from_domain, "auto-aleg-full")) {
const char *sip_full_from = switch_channel_get_variable(o_channel, "sip_full_from");
if (!zstr(sip_full_from)) {
switch_channel_set_variable(nchannel, "sip_force_full_from", sip_full_from);
}
} else if (!strcasecmp(gateway_ptr->from_domain, "auto-aleg-domain")) {
const char *sip_from_host = switch_channel_get_variable(o_channel, "sip_from_host");
if (!zstr(sip_from_host)) {
switch_channel_set_variable(nchannel, "sip_invite_domain", sip_from_host);
}
} else {
switch_channel_set_variable(nchannel, "sip_invite_domain", gateway_ptr->from_domain);
}
}
if (!zstr(gateway_ptr->outbound_sticky_proxy) && !switch_channel_get_variable(nchannel, "sip_route_uri")) {
switch_channel_set_variable(nchannel, "sip_route_uri", gateway_ptr->outbound_sticky_proxy);
}
} else {
if (!(dest = strchr(profile_name, '/'))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL\n");
2011-12-15 17:16:41 +00:00
cause = SWITCH_CAUSE_INVALID_URL;
goto error;
}
*dest++ = '\0';
if (!(profile = sofia_glue_find_profile(profile_name))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Profile\n");
2011-12-15 17:16:41 +00:00
cause = SWITCH_CAUSE_INVALID_PROFILE;
goto error;
}
if (sofia_test_pflag(profile, PFLAG_STANDBY)) {
2011-12-16 20:41:48 +00:00
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "System Paused\n");
cause = SWITCH_CAUSE_SYSTEM_SHUTDOWN;
goto error;
}
2010-12-29 21:04:19 +00:00
if (profile->domain_name && strcmp(profile->domain_name, profile->name)) {
profile_name = profile->domain_name;
}
if (!strncasecmp(dest, "sip:", 4) || !strncasecmp(dest, "sips:", 5)) {
2010-08-18 19:58:14 +00:00
char *c;
tech_pvt->dest = switch_core_session_strdup(nsession, dest);
2010-08-18 19:58:14 +00:00
if ((c = strchr(tech_pvt->dest, ':'))) {
c++;
tech_pvt->e_dest = switch_core_session_strdup(nsession, c);
}
} else if (!mod && !strchr(dest, '@') && (host = strchr(dest, '%'))) {
char buf[1024];
*host = '@';
tech_pvt->e_dest = switch_core_session_strdup(nsession, dest);
*host++ = '\0';
if (sofia_reg_find_reg_url(profile, dest, host, buf, sizeof(buf))) {
tech_pvt->dest = switch_core_session_strdup(nsession, buf);
tech_pvt->local_url = switch_core_session_sprintf(nsession, "%s@%s", dest, host);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot locate registered user %s@%s\n", dest, host);
cause = SWITCH_CAUSE_USER_NOT_REGISTERED;
goto error;
}
} else if (!(host = strchr(dest, '@'))) {
char buf[1024];
tech_pvt->e_dest = switch_core_session_strdup(nsession, dest);
if (sofia_reg_find_reg_url(profile, dest, profile_name, buf, sizeof(buf))) {
tech_pvt->dest = switch_core_session_strdup(nsession, buf);
tech_pvt->local_url = switch_core_session_sprintf(nsession, "%s@%s", dest, profile_name);
host = profile_name;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot locate registered user %s@%s\n", dest, profile_name);
cause = SWITCH_CAUSE_USER_NOT_REGISTERED;
goto error;
}
} else {
host++;
if (!strchr(host, '.') || switch_true(switch_event_get_header(var_event, "sip_gethostbyname"))) {
2013-07-12 18:35:59 +00:00
struct sockaddr_in sa;
struct hostent *he = gethostbyname(host);
char buf[50] = "", *tmp;
const char *ip;
2013-07-12 18:35:59 +00:00
if (he) {
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
2014-02-11 22:31:21 +00:00
ip = switch_inet_ntop(AF_INET, &sa.sin_addr, buf, sizeof(buf));
2013-07-12 18:35:59 +00:00
tmp = switch_string_replace(dest, host, ip);
//host = switch_core_session_strdup(nsession, ip);
//dest = switch_core_session_strdup(nsession, tmp);
switch_channel_set_variable_printf(nchannel, "sip_route_uri", "sip:%s", tmp);
free(tmp);
}
}
tech_pvt->dest = switch_core_session_alloc(nsession, strlen(dest) + 5);
2010-08-18 19:58:14 +00:00
tech_pvt->e_dest = switch_core_session_strdup(nsession, dest);
switch_snprintf(tech_pvt->dest, strlen(dest) + 5, "sip:%s", dest);
}
}
switch_channel_set_variable_printf(nchannel, "sip_local_network_addr", "%s", profile->extsipip ? profile->extsipip : profile->sipip);
switch_channel_set_variable(nchannel, "sip_profile_name", profile_name);
if (switch_stristr("fs_path", tech_pvt->dest)) {
char *remote_host = NULL;
const char *s;
if ((s = switch_stristr("fs_path=", tech_pvt->dest))) {
s += 8;
}
if (s) {
remote_host = switch_core_session_strdup(nsession, s);
switch_url_decode(remote_host);
}
if (!zstr(remote_host)) {
2012-12-22 00:06:09 +00:00
switch_split_user_domain(remote_host, NULL, &tech_pvt->mparams.remote_ip);
}
}
2012-12-22 00:06:09 +00:00
if (zstr(tech_pvt->mparams.remote_ip)) {
switch_split_user_domain(switch_core_session_strdup(nsession, tech_pvt->dest), NULL, &tech_pvt->mparams.remote_ip);
}
if (dest_to) {
if (strchr(dest_to, '@')) {
tech_pvt->dest_to = switch_core_session_sprintf(nsession, "sip:%s", dest_to);
} else {
tech_pvt->dest_to = switch_core_session_sprintf(nsession, "sip:%s@%s", dest_to, host ? host : profile->sipip);
}
}
if (!tech_pvt->dest_to) {
tech_pvt->dest_to = tech_pvt->dest;
}
if (!zstr(tech_pvt->dest) && switch_stristr("transport=ws", tech_pvt->dest)) {
switch_channel_set_variable(nchannel, "media_webrtc", "true");
switch_core_session_set_ice(nsession);
}
sofia_glue_attach_private(nsession, profile, tech_pvt, dest);
if (tech_pvt->local_url) {
switch_channel_set_variable(nchannel, "sip_local_url", tech_pvt->local_url);
if (profile->pres_type) {
const char *presence_id = switch_channel_get_variable(nchannel, "presence_id");
if (zstr(presence_id)) {
switch_channel_set_variable(nchannel, "presence_id", tech_pvt->local_url);
}
}
}
switch_channel_set_variable(nchannel, "sip_destination_url", tech_pvt->dest);
#if 0
dest_num = switch_core_session_strdup(nsession, dest);
if ((p = strchr(dest_num, '@'))) {
*p = '\0';
if ((p = strrchr(dest_num, '/'))) {
dest_num = p + 1;
} else if ((p = (char *) switch_stristr("sip:", dest_num))) {
dest_num = p + 4;
} else if ((p = (char *) switch_stristr("sips:", dest_num))) {
dest_num = p + 5;
}
}
2010-06-18 18:39:55 +00:00
if (profile->pres_type) {
char *sql;
time_t now;
2010-06-18 18:39:55 +00:00
const char *presence_id = switch_channel_get_variable(nchannel, "presence_id");
const char *presence_data = switch_channel_get_variable(nchannel, "presence_data");
if (zstr(presence_id)) {
presence_id = switch_event_get_header(var_event, "presence_id");
}
if (zstr(presence_data)) {
presence_data = switch_event_get_header(var_event, "presence_data");
}
now = switch_epoch_time_now(NULL);
2012-02-18 01:47:57 +00:00
sql = switch_mprintf("insert into sip_dialogs (uuid,presence_id,presence_data,profile_name,hostname,rcd,call_info_state) "
"values ('%q', '%q', '%q', '%q', '%q', %ld, '')", switch_core_session_get_uuid(nsession),
switch_str_nil(presence_id), switch_str_nil(presence_data), profile->name, mod_sofia_globals.hostname, (long) now);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
2010-06-18 18:39:55 +00:00
}
#endif
2010-06-23 18:22:52 +00:00
2010-06-18 18:39:55 +00:00
caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
2010-06-23 18:22:52 +00:00
caller_profile->destination_number = switch_sanitize_number(caller_profile->destination_number);
not_const = (char *) caller_profile->caller_id_name;
caller_profile->caller_id_name = switch_sanitize_number(not_const);
not_const = (char *) caller_profile->caller_id_number;
caller_profile->caller_id_number = switch_sanitize_number(not_const);
2012-07-12 23:10:20 +00:00
//caller_profile->destination_number = switch_core_strdup(caller_profile->pool, dest_num);
switch_channel_set_caller_profile(nchannel, caller_profile);
2012-07-12 23:10:20 +00:00
if (gateway_ptr && gateway_ptr->ob_vars) {
switch_event_header_t *hp;
for (hp = gateway_ptr->ob_vars->headers; hp; hp = hp->next) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s setting variable [%s]=[%s]\n",
switch_channel_get_name(nchannel), hp->name, hp->value);
if (!strncmp(hp->name, "p:", 2)) {
switch_channel_set_profile_var(nchannel, hp->name + 2, hp->value);
} else {
switch_channel_set_variable(nchannel, hp->name, hp->value);
}
}
}
sofia_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
sofia_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION);
if (switch_channel_get_state(nchannel) == CS_NEW) {
switch_channel_set_state(nchannel, CS_INIT);
}
tech_pvt->caller_profile = caller_profile;
*new_session = nsession;
cause = SWITCH_CAUSE_SUCCESS;
if ((hval = switch_event_get_header(var_event, "sip_enable_soa"))) {
if (switch_true(hval)) {
sofia_set_flag(tech_pvt, TFLAG_ENABLE_SOA);
} else {
sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
}
}
if ((hval = switch_event_get_header(var_event, "sip_auto_answer")) && switch_true(hval)) {
switch_channel_set_variable_printf(nchannel, "sip_h_Call-Info", "<sip:%s>;answer-after=0", profile->sipip);
switch_channel_set_variable(nchannel, "sip_invite_params", "intercom=true");
}
if (((hval = switch_event_get_header(var_event, "effective_callee_id_name")) ||
(hval = switch_event_get_header(var_event, "sip_callee_id_name"))) && !zstr(hval)) {
caller_profile->callee_id_name = switch_core_strdup(caller_profile->pool, hval);
}
if (((hval = switch_event_get_header(var_event, "effective_callee_id_number")) ||
(hval = switch_event_get_header(var_event, "sip_callee_id_number"))) && !zstr(hval)) {
caller_profile->callee_id_number = switch_core_strdup(caller_profile->pool, hval);
}
if (session) {
const char *vval = NULL;
switch_ivr_transfer_variable(session, nsession, SOFIA_REPLACES_HEADER);
if (!(vval = switch_channel_get_variable(o_channel, "sip_copy_custom_headers")) || switch_true(vval)) {
switch_ivr_transfer_variable(session, nsession, SOFIA_SIP_HEADER_PREFIX_T);
}
if (!(vval = switch_channel_get_variable(o_channel, "sip_copy_multipart")) || switch_true(vval)) {
switch_ivr_transfer_variable(session, nsession, "sip_multipart");
}
switch_ivr_transfer_variable(session, nsession, "rtp_video_fmtp");
switch_ivr_transfer_variable(session, nsession, "sip-force-contact");
switch_ivr_transfer_variable(session, nsession, "sip_sticky_contact");
2010-06-05 00:37:04 +00:00
if (!cid_locked) {
switch_ivr_transfer_variable(session, nsession, "sip_cid_type");
}
if (switch_core_session_compare(session, nsession)) {
/* It's another sofia channel! so lets cache what they use as a pt for telephone event so
we can keep it the same
2010-06-30 15:35:03 +00:00
*/
private_object_t *ctech_pvt;
ctech_pvt = switch_core_session_get_private(session);
switch_assert(ctech_pvt != NULL);
tech_pvt->bte = ctech_pvt->te;
tech_pvt->bcng_pt = ctech_pvt->cng_pt;
2010-06-05 00:37:04 +00:00
if (!cid_locked) {
tech_pvt->cid_type = ctech_pvt->cid_type;
}
if (sofia_test_flag(tech_pvt, TFLAG_ENABLE_SOA)) {
sofia_set_flag(ctech_pvt, TFLAG_ENABLE_SOA);
} else {
sofia_clear_flag(ctech_pvt, TFLAG_ENABLE_SOA);
}
2011-06-15 15:29:07 +00:00
if (switch_channel_test_flag(o_channel, CF_ZRTP_PASSTHRU_REQ) && switch_channel_test_flag(o_channel, CF_ZRTP_HASH)) {
add enhanced zrtp passthrough (zrtp passthru) mode ZRTP passthrough mode allows two ZRTP-capable clients to negotiate an end-to-end security association through FreeSWITCH. The clients are therefore able to be certain that the FreeSWITCH instance mediating the call cannot eavesdrop on their conversation. Importantly, this capability is maintained across multiple FreeSWITCH hops. If widely deployed, this enables a global network architecture where two people can speak securely with strong cryptographically protected authentication and confidentiality. With this commit we implement a zrtp-passthru mode that handles all the details of the negotiation intelligently. This mode can be selected by setting the boolean parameter inbound-zrtp-passthru in the sofia profile. This will also force late-negotiation as it is essential for correctly negotiating an end-to-end ZRTP security association. When an incoming call with a zrtp-hash is received and this mode is enabled, we find the first audio and the first video zrtp-hash in the SDP and store them as remote values on this channel. Once a b-leg is available, we set the local zrtp-hash values on that channel to the remote zrtp-hash values collected from the a-leg. Because zrtp-passthru absolutely requires that the channels negotiate the same codec, we offer to the b-leg only codecs that the a-leg can speak. Once the b-leg accepts a codec, we will force that choice onto the a-leg. If the b-leg sends us zrtp-hash values in the signaling, we store those as remote values on the b-leg and copy them to the local values on the a-leg. At this point, each leg has the zrtp-hash values from the other, and we know we can do ZRTP passthrough mode on the call. We send the b-leg's zrtp-hash back to the a-leg in the 200 OK. We then enable UDPTL mode on the rtp streams for both the audio and the video so that we don't interfere in the ZRTP negotiation. If the b-leg fails to return a zrtp-hash in the signaling, we set up a ZRTP security association with the a-leg ourselves, if we are so equipped. Likewise, if the a-leg fails to send a zrtp-hash in the signaling, we attempt to set up a ZRTP security association ourselves with the b-leg. The zrtp-passthru mode can also be enabled in the dialplan by setting the boolean channel variable zrtp_passthru. If enabled in this manner, we can't force late-negotiation, so the user would need to be sure this is configured. If ZRTP passthrough mode is not enabled in either manner, this change should have no effect. Channel variables for each of the various zrtp-hash values are set, though it is anticipated that there is no good reason to use them, so they may be removed without warning. For checking whether zrtp passthrough mode was successful, we provide the channel variable zrtp_passthru_active which is set on both legs. Though not implemented by this commit, the changes here should make it more straightforward to add correct zrtp-hash values to the signaling and verify that correct hello hash values are received when FreeSWITCH is acting as a terminating leg of the ZRTP security association. A historical note... This commit replaces the recently-added sdp_zrtp_hash_string method, commit 2ab1605a8887adc62be1b75f6ef67af87ff080de. This prior method sets a channel variable from the a-leg's zrtp-hash, then relies on the dialplan to export this channel variable to the b-leg, where it is put into the SDP. While it was a great start and wonderful for testing, this approach has some drawbacks that motivated the present work: * There's no good way to pass the zrtp-hash from the b-leg back to the a-leg. In fact, the implementation seems to send the a-leg's zrtp-hash back to the originating client in the 200 OK. This is not correct. * To support video, we'd need to have a separate dialplan variable, and the dialplan author would need to deal with that explicitly. * The API is problematic as it requires the dialplan author to understand intricate details of how ZRTP works to implement a correct dialplan. Further, by providing too fine-grained control (but at the same time, not enough control) it would limit our ability to make the behavior smarter once people started relying on this.
2012-05-24 20:39:03 +00:00
const char *x = NULL;
2012-12-21 04:57:47 +00:00
switch_core_media_pass_zrtp_hash2(session, nsession);
add enhanced zrtp passthrough (zrtp passthru) mode ZRTP passthrough mode allows two ZRTP-capable clients to negotiate an end-to-end security association through FreeSWITCH. The clients are therefore able to be certain that the FreeSWITCH instance mediating the call cannot eavesdrop on their conversation. Importantly, this capability is maintained across multiple FreeSWITCH hops. If widely deployed, this enables a global network architecture where two people can speak securely with strong cryptographically protected authentication and confidentiality. With this commit we implement a zrtp-passthru mode that handles all the details of the negotiation intelligently. This mode can be selected by setting the boolean parameter inbound-zrtp-passthru in the sofia profile. This will also force late-negotiation as it is essential for correctly negotiating an end-to-end ZRTP security association. When an incoming call with a zrtp-hash is received and this mode is enabled, we find the first audio and the first video zrtp-hash in the SDP and store them as remote values on this channel. Once a b-leg is available, we set the local zrtp-hash values on that channel to the remote zrtp-hash values collected from the a-leg. Because zrtp-passthru absolutely requires that the channels negotiate the same codec, we offer to the b-leg only codecs that the a-leg can speak. Once the b-leg accepts a codec, we will force that choice onto the a-leg. If the b-leg sends us zrtp-hash values in the signaling, we store those as remote values on the b-leg and copy them to the local values on the a-leg. At this point, each leg has the zrtp-hash values from the other, and we know we can do ZRTP passthrough mode on the call. We send the b-leg's zrtp-hash back to the a-leg in the 200 OK. We then enable UDPTL mode on the rtp streams for both the audio and the video so that we don't interfere in the ZRTP negotiation. If the b-leg fails to return a zrtp-hash in the signaling, we set up a ZRTP security association with the a-leg ourselves, if we are so equipped. Likewise, if the a-leg fails to send a zrtp-hash in the signaling, we attempt to set up a ZRTP security association ourselves with the b-leg. The zrtp-passthru mode can also be enabled in the dialplan by setting the boolean channel variable zrtp_passthru. If enabled in this manner, we can't force late-negotiation, so the user would need to be sure this is configured. If ZRTP passthrough mode is not enabled in either manner, this change should have no effect. Channel variables for each of the various zrtp-hash values are set, though it is anticipated that there is no good reason to use them, so they may be removed without warning. For checking whether zrtp passthrough mode was successful, we provide the channel variable zrtp_passthru_active which is set on both legs. Though not implemented by this commit, the changes here should make it more straightforward to add correct zrtp-hash values to the signaling and verify that correct hello hash values are received when FreeSWITCH is acting as a terminating leg of the ZRTP security association. A historical note... This commit replaces the recently-added sdp_zrtp_hash_string method, commit 2ab1605a8887adc62be1b75f6ef67af87ff080de. This prior method sets a channel variable from the a-leg's zrtp-hash, then relies on the dialplan to export this channel variable to the b-leg, where it is put into the SDP. While it was a great start and wonderful for testing, this approach has some drawbacks that motivated the present work: * There's no good way to pass the zrtp-hash from the b-leg back to the a-leg. In fact, the implementation seems to send the a-leg's zrtp-hash back to the originating client in the 200 OK. This is not correct. * To support video, we'd need to have a separate dialplan variable, and the dialplan author would need to deal with that explicitly. * The API is problematic as it requires the dialplan author to understand intricate details of how ZRTP works to implement a correct dialplan. Further, by providing too fine-grained control (but at the same time, not enough control) it would limit our ability to make the behavior smarter once people started relying on this.
2012-05-24 20:39:03 +00:00
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "[zrtp_passthru] Setting a-leg inherit_codec=true\n");
switch_channel_set_variable(o_channel, "inherit_codec", "true");
if ((x = switch_channel_get_variable(o_channel, "ep_codec_string"))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "[zrtp_passthru] Setting b-leg absolute_codec_string='%s'\n", x);
switch_channel_set_variable(nchannel, "absolute_codec_string", x);
}
}
2011-06-15 15:29:07 +00:00
/* SNARK: lets copy this across so we can see if we're the other leg of 3PCC + bypass_media... */
if (sofia_test_flag(ctech_pvt, TFLAG_3PCC) && (switch_channel_test_flag(o_channel, CF_PROXY_MODE) || switch_channel_test_flag(o_channel, CF_PROXY_MEDIA))) {
sofia_set_flag(tech_pvt, TFLAG_3PCC_INVITE);
sofia_set_flag(tech_pvt, TFLAG_LATE_NEGOTIATION);
} else {
sofia_clear_flag(tech_pvt, TFLAG_3PCC_INVITE);
}
}
2013-02-27 20:16:00 +00:00
switch_core_media_check_outgoing_proxy(nsession, session);
}
goto done;
2010-06-30 15:35:03 +00:00
error:
2011-06-07 02:28:14 +00:00
if (gateway_ptr) {
sofia_reg_release_gateway(gateway_ptr);
}
if (nsession) {
switch_core_session_destroy(&nsession);
}
2010-05-04 20:48:36 +00:00
if (pool) {
*pool = NULL;
}
2010-06-30 15:35:03 +00:00
done:
if (profile) {
if (cause == SWITCH_CAUSE_SUCCESS) {
profile->ob_calls++;
} else {
profile->ob_failed_calls++;
}
sofia_glue_release_profile(profile);
}
return cause;
}
static int notify_csta_callback(void *pArg, int argc, char **argv, char **columnNames)
{
nua_handle_t *nh;
sofia_profile_t *ext_profile = NULL, *profile = (sofia_profile_t *) pArg;
int i = 0;
char *user = argv[i++];
char *host = argv[i++];
char *contact_in = argv[i++];
char *profile_name = argv[i++];
char *call_id = argv[i++];
char *full_from = argv[i++];
char *full_to = argv[i++];
int expires = atoi(argv[i++]);
char *body = argv[i++];
char *ct = argv[i++];
char *id = NULL;
char *contact;
2013-10-16 14:56:01 +00:00
sip_cseq_t *cseq = NULL;
uint32_t callsequence;
sofia_destination_t *dst = NULL;
char *route_uri = NULL;
time_t epoch_now = switch_epoch_time_now(NULL);
time_t expires_in = (expires - epoch_now);
char *extra_headers = switch_mprintf("Subscription-State: active, %d\r\n", expires_in);
if (profile_name && strcasecmp(profile_name, profile->name)) {
if ((ext_profile = sofia_glue_find_profile(profile_name))) {
profile = ext_profile;
}
}
id = switch_mprintf("sip:%s@%s", user, host);
switch_assert(id);
contact = sofia_glue_get_url_from_contact(contact_in, 1);
dst = sofia_glue_get_destination((char *) contact);
if (dst->route_uri) {
route_uri = sofia_glue_strip_uri(dst->route_uri);
}
callsequence = sofia_presence_get_cseq(profile);
2013-10-16 14:56:01 +00:00
//nh = nua_handle(profile->nua, NULL, NUTAG_URL(dst->contact), SIPTAG_FROM_STR(id), SIPTAG_TO_STR(id), SIPTAG_CONTACT_STR(profile->url), TAG_END());
2013-10-16 14:56:01 +00:00
nh = nua_handle(profile->nua, NULL, NUTAG_URL(dst->contact), SIPTAG_FROM_STR(full_to), SIPTAG_TO_STR(full_from), SIPTAG_CONTACT_STR(profile->url), TAG_END());
cseq = sip_cseq_create(nh->nh_home, callsequence, SIP_METHOD_NOTIFY);
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
nua_notify(nh, NUTAG_NEWSUB(1),
TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_EVENT_STR("as-feature-event"), SIPTAG_CONTENT_TYPE_STR(ct), TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)), SIPTAG_CSEQ(cseq),
TAG_END());
switch_safe_free(route_uri);
sofia_glue_free_destination(dst);
2015-12-10 04:36:41 +00:00
free(extra_headers);
free(id);
free(contact);
if (ext_profile) {
sofia_glue_release_profile(ext_profile);
}
return 0;
}
static int notify_callback(void *pArg, int argc, char **argv, char **columnNames)
{
nua_handle_t *nh;
sofia_profile_t *ext_profile = NULL, *profile = (sofia_profile_t *) pArg;
char *user = argv[0];
char *host = argv[1];
char *contact_in = argv[2];
char *profile_name = argv[3];
char *ct = argv[4];
char *es = argv[5];
char *body = argv[6];
char *id = NULL;
2010-11-02 16:50:04 +00:00
char *contact;
sofia_destination_t *dst = NULL;
char *route_uri = NULL;
if (profile_name && strcasecmp(profile_name, profile->name)) {
if ((ext_profile = sofia_glue_find_profile(profile_name))) {
profile = ext_profile;
}
}
id = switch_mprintf("sip:%s@%s", user, host);
switch_assert(id);
contact = sofia_glue_get_url_from_contact(contact_in, 1);
2010-11-02 16:50:04 +00:00
dst = sofia_glue_get_destination((char *) contact);
2010-11-02 16:50:04 +00:00
if (dst->route_uri) {
route_uri = sofia_glue_strip_uri(dst->route_uri);
}
2010-11-02 16:50:04 +00:00
nh = nua_handle(profile->nua, NULL, NUTAG_URL(dst->contact), SIPTAG_FROM_STR(id), SIPTAG_TO_STR(id), SIPTAG_CONTACT_STR(profile->url), TAG_END());
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
nua_notify(nh, NUTAG_NEWSUB(1), SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
2010-11-02 16:50:04 +00:00
TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)),
SIPTAG_EVENT_STR(es), SIPTAG_CONTENT_TYPE_STR(ct), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)), TAG_END());
2010-11-02 16:50:04 +00:00
switch_safe_free(route_uri);
sofia_glue_free_destination(dst);
free(id);
free(contact);
if (ext_profile) {
sofia_glue_release_profile(ext_profile);
}
return 0;
}
2016-02-17 22:22:46 +00:00
void general_event_handler(switch_event_t *event)
{
switch (event->event_id) {
case SWITCH_EVENT_NOTIFY:
{
const char *profile_name = switch_event_get_header(event, "profile");
const char *ct = switch_event_get_header(event, "content-type");
const char *es = switch_event_get_header(event, "event-string");
const char *user = switch_event_get_header(event, "user");
const char *host = switch_event_get_header(event, "host");
const char *call_id = switch_event_get_header(event, "call-id");
const char *uuid = switch_event_get_header(event, "uuid");
const char *body = switch_event_get_body(event);
const char *to_uri = switch_event_get_header(event, "to-uri");
const char *from_uri = switch_event_get_header(event, "from-uri");
2012-06-19 18:22:57 +00:00
const char *extra_headers = switch_event_get_header(event, "extra-headers");
const char *contact_uri = switch_event_get_header(event, "contact-uri");
const char *no_sub_state = switch_event_get_header(event, "no-sub-state");
2012-06-19 18:22:57 +00:00
sofia_profile_t *profile;
if (contact_uri) {
if (!es) {
es = "message-summary";
}
if (!ct) {
ct = "application/simple-message-summary";
}
if (!profile_name) {
profile_name = "default";
}
if (!(profile = sofia_glue_find_profile(profile_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find profile %s\n", profile_name);
return;
}
if (to_uri && from_uri) {
sofia_destination_t *dst = NULL;
nua_handle_t *nh;
char *route_uri = NULL;
char *sip_sub_st = NULL;
dst = sofia_glue_get_destination((char *) contact_uri);
if (dst->route_uri) {
route_uri = sofia_glue_strip_uri(dst->route_uri);
}
if (zstr(dst->contact)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid contact uri [%s]\n", switch_str_nil(dst->contact));
return;
}
nh = nua_handle(profile->nua,
NULL,
NUTAG_URL(dst->contact),
SIPTAG_FROM_STR(from_uri),
SIPTAG_TO_STR(to_uri),
SIPTAG_CONTACT_STR(profile->url),
TAG_END());
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
if (!switch_true(no_sub_state)) {
sip_sub_st = "terminated;reason=noresource";
}
nua_notify(nh,
NUTAG_NEWSUB(1), TAG_IF(sip_sub_st, SIPTAG_SUBSCRIPTION_STATE_STR(sip_sub_st)),
TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)),
SIPTAG_EVENT_STR(es), SIPTAG_CONTENT_TYPE_STR(ct), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_END());
switch_safe_free(route_uri);
sofia_glue_free_destination(dst);
sofia_glue_release_profile(profile);
}
return;
} else if (to_uri || from_uri) {
if (!es) {
es = "message-summary";
}
if (!ct) {
ct = "application/simple-message-summary";
}
if (!profile_name) {
profile_name = "default";
}
if (!(profile = sofia_glue_find_profile(profile_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find profile %s\n", profile_name);
return;
}
if (to_uri && from_uri) {
sofia_destination_t *dst = NULL;
nua_handle_t *nh;
char *route_uri = NULL;
dst = sofia_glue_get_destination((char *) to_uri);
if (dst->route_uri) {
route_uri = sofia_glue_strip_uri(dst->route_uri);
}
nh = nua_handle(profile->nua,
NULL,
NUTAG_URL(to_uri),
SIPTAG_FROM_STR(from_uri),
SIPTAG_TO_STR(to_uri),
SIPTAG_CONTACT_STR(profile->url),
TAG_END());
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
nua_notify(nh,
NUTAG_NEWSUB(1), SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)),
SIPTAG_EVENT_STR(es), SIPTAG_CONTENT_TYPE_STR(ct), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_END());
switch_safe_free(route_uri);
sofia_glue_free_destination(dst);
sofia_glue_release_profile(profile);
}
return;
}
if (uuid && ct && es) {
switch_core_session_t *session;
private_object_t *tech_pvt;
if ((session = switch_core_session_locate(uuid))) {
if ((tech_pvt = switch_core_session_get_private(session))) {
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
nua_notify(tech_pvt->nh,
NUTAG_NEWSUB(1), SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
SIPTAG_EVENT_STR(es), SIPTAG_CONTENT_TYPE_STR(ct), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
}
switch_core_session_rwunlock(session);
}
} else if (profile_name && ct && es && user && host && (profile = sofia_glue_find_profile(profile_name))) {
char *sql;
if (call_id) {
sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,'%q','%q','%q' "
"from sip_registrations where call_id='%q'", ct, es, switch_str_nil(body), call_id);
} else {
if (!strcasecmp(es, "message-summary")) {
sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,'%q','%q','%q' "
2016-11-11 17:27:35 +00:00
"from sip_registrations where mwi_user='%q' and mwi_host='%q'",
ct, es, switch_str_nil(body), switch_str_nil(user), switch_str_nil(host)
2010-06-30 15:35:03 +00:00
);
} else {
sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,'%q','%q','%q' "
2016-11-11 17:27:35 +00:00
"from sip_registrations where sip_user='%q' and sip_host='%q'",
ct, es, switch_str_nil(body), switch_str_nil(user), switch_str_nil(host)
2010-06-30 15:35:03 +00:00
);
}
}
switch_mutex_lock(profile->dbh_mutex);
sofia_glue_execute_sql_callback(profile, NULL, sql, notify_callback, profile);
switch_mutex_unlock(profile->dbh_mutex);
sofia_glue_release_profile(profile);
free(sql);
}
}
break;
case SWITCH_EVENT_PHONE_FEATURE:
{
const char *profile_name = switch_event_get_header(event, "profile");
const char *user = switch_event_get_header(event, "user");
const char *host = switch_event_get_header(event, "host");
const char *call_id = switch_event_get_header(event, "call-id");
const char *csta_event = switch_event_get_header(event, "Feature-Event");
char *ct = "application/x-as-feature-event+xml";
2015-12-10 04:36:41 +00:00
char *ct_m = NULL;
sofia_profile_t *profile;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Phone Feature NOTIFY\n");
if (profile_name && user && host && (profile = sofia_glue_find_profile(profile_name))) {
char *sql;
switch_stream_handle_t stream = { 0 };
SWITCH_STANDARD_STREAM(stream);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "we have all required vars\n");
if (csta_event) {
if (!strcmp(csta_event, "init")) {
char *boundary_string = "UniqueFreeSWITCHBoundary";
switch_stream_handle_t dnd_stream = { 0 };
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending multipart with DND and CFWD\n");
2014-05-15 18:30:03 +00:00
if (switch_event_get_header(event, "forward_immediate")) {
switch_stream_handle_t fwdi_stream = { 0 };
SWITCH_STANDARD_STREAM(fwdi_stream);
write_csta_xml_chunk(event, fwdi_stream, "ForwardingEvent", "forwardImmediate");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)fwdi_stream.data, (int)strlen(fwdi_stream.data));
2013-10-16 14:56:01 +00:00
stream.write_function(&stream, "--%s\r\nContent-Type: application/x-as-feature-event+xml\r\nContent-Length: %d\r\nContent-ID: <%si@%s>\r\n\r\n%s", boundary_string, strlen(fwdi_stream.data), user, host, fwdi_stream.data);
switch_safe_free(fwdi_stream.data);
}
2014-05-15 18:30:03 +00:00
if (switch_event_get_header(event, "forward_busy")) {
switch_stream_handle_t fwdb_stream = { 0 };
SWITCH_STANDARD_STREAM(fwdb_stream);
write_csta_xml_chunk(event, fwdb_stream, "ForwardingEvent", "forwardBusy");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)fwdb_stream.data, (int)strlen(fwdb_stream.data));
2013-10-16 14:56:01 +00:00
stream.write_function(&stream, "--%s\r\nContent-Type: application/x-as-feature-event+xml\r\nContent-Length: %d\r\nContent-ID: <%sb@%s>\r\n\r\n%s", boundary_string, strlen(fwdb_stream.data), user, host, fwdb_stream.data);
switch_safe_free(fwdb_stream.data);
}
2014-05-15 18:30:03 +00:00
if (switch_event_get_header(event, "forward_no_answer")) {
switch_stream_handle_t fwdna_stream = { 0 };
SWITCH_STANDARD_STREAM(fwdna_stream);
write_csta_xml_chunk(event, fwdna_stream, "ForwardingEvent", "forwardNoAns");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)fwdna_stream.data, (int)strlen(fwdna_stream.data));
2013-10-16 14:56:01 +00:00
stream.write_function(&stream, "--%s\r\nContent-Type: application/x-as-feature-event+xml\r\nContent-Length: %d\r\nContent-ID: <%sn@%s>\r\n\r\n%s", boundary_string, strlen(fwdna_stream.data), user, host, fwdna_stream.data);
switch_safe_free(fwdna_stream.data);
}
SWITCH_STANDARD_STREAM(dnd_stream);
write_csta_xml_chunk(event, dnd_stream, "DoNotDisturbEvent", NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)dnd_stream.data, (int)strlen(dnd_stream.data));
2013-10-16 14:56:01 +00:00
stream.write_function(&stream, "--%s\r\nContent-Type: application/x-as-feature-event+xml\r\nContent-Length: %d\r\nContent-ID: <%sd@%s>\r\n\r\n%s", boundary_string, strlen(dnd_stream.data), user, host, dnd_stream.data);
switch_safe_free(dnd_stream.data);
2013-10-16 14:56:01 +00:00
stream.write_function(&stream, "--%s--\r\n", boundary_string);
2015-12-10 04:36:41 +00:00
ct_m = switch_mprintf("multipart/mixed; boundary=\"%s\"", boundary_string);
ct = ct_m;
} else {
char *fwd_type = NULL;
2014-04-28 19:00:22 +00:00
if (switch_event_get_header(event, "forward_immediate")) {
fwd_type = "forwardImmediate";
2014-04-28 19:00:22 +00:00
} else if (switch_event_get_header(event, "forward_busy")) {
fwd_type = "forwardBusy";
2014-04-28 19:00:22 +00:00
} else if (switch_event_get_header(event, "forward_no_answer")) {
fwd_type = "forwardNoAns";
}
// this will need some work to handle the different types of forwarding events
write_csta_xml_chunk(event, stream, csta_event, fwd_type);
}
}
if (call_id) {
sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,call_id,full_from,full_to,expires,'%q', '%q' "
"from sip_subscriptions where event='as-feature-event' and call_id='%q'", stream.data, ct, call_id);
} else {
sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,call_id,full_from,full_to,expires,'%q', '%q' "
2016-11-11 17:27:35 +00:00
"from sip_subscriptions where event='as-feature-event' and sip_user='%q' and sip_host='%q'", stream.data, ct, switch_str_nil(user), switch_str_nil(host)
);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query: %s\n", sql);
switch_safe_free(stream.data);
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_callback(profile, NULL, sql, notify_csta_callback, profile);
switch_mutex_unlock(profile->ireg_mutex);
sofia_glue_release_profile(profile);
free(sql);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "missing something\n");
}
2015-12-10 04:36:41 +00:00
switch_safe_free(ct_m);
}
break;
case SWITCH_EVENT_SEND_MESSAGE:
{
const char *profile_name = switch_event_get_header(event, "profile");
const char *ct = switch_event_get_header(event, "content-type");
const char *user = switch_event_get_header(event, "user");
const char *host = switch_event_get_header(event, "host");
2010-06-10 20:47:13 +00:00
const char *subject = switch_event_get_header(event, "subject");
2012-08-31 20:35:13 +00:00
const char *uuid = switch_event_get_header(event, "uuid");
const char *body = switch_event_get_body(event);
2012-08-31 20:35:13 +00:00
sofia_profile_t *profile;
nua_handle_t *nh;
2012-08-31 20:35:13 +00:00
if (ct && user && host) {
char *id = NULL;
char *contact, *p;
2010-08-18 19:58:14 +00:00
switch_console_callback_match_t *list = NULL;
switch_console_callback_match_node_t *m;
2014-01-09 19:30:41 +00:00
if (!profile_name || !(profile = sofia_glue_find_profile(profile_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find profile %s\n", profile_name);
return;
}
2010-08-18 19:58:14 +00:00
if (!(list = sofia_reg_find_reg_url_multi(profile, user, host))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find registered user %s@%s\n", user, host);
return;
}
id = switch_mprintf("sip:%s@%s", user, host);
switch_assert(id);
2012-08-31 20:35:13 +00:00
2010-08-18 19:58:14 +00:00
for (m = list->head; m; m = m->next) {
contact = sofia_glue_get_url_from_contact(m->val, 0);
if ((p = strstr(contact, ";fs_"))) {
*p = '\0';
}
2010-08-18 19:58:14 +00:00
nh = nua_handle(profile->nua,
NULL, NUTAG_URL(contact), SIPTAG_FROM_STR(id), SIPTAG_TO_STR(id), SIPTAG_CONTACT_STR(profile->url), TAG_END());
2010-08-18 19:58:14 +00:00
nua_message(nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR(ct),
TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)), TAG_IF(!zstr(subject), SIPTAG_SUBJECT_STR(subject)), TAG_END());
}
2011-05-27 14:38:54 +00:00
free(id);
2010-08-18 19:58:14 +00:00
switch_console_free_matches(&list);
sofia_glue_release_profile(profile);
2012-08-31 20:35:13 +00:00
} else if (uuid && ct) {
switch_core_session_t *session;
private_object_t *tech_pvt;
2012-08-31 20:35:13 +00:00
if ((session = switch_core_session_locate(uuid))) {
if ((tech_pvt = switch_core_session_get_private(session))) {
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
2012-08-31 20:35:13 +00:00
nua_message(tech_pvt->nh,
SIPTAG_CONTENT_TYPE_STR(ct), SIPTAG_PAYLOAD_STR(body),
FS-11557: [mod_sofia] add support for RFC 7989 Session-ID header (enable with sofia profile param rfc-7989=true) FS-11557 [mod_sofia, mod_conference, core] Add support for re-INVITE when setting Session-ID in conference after call has been answered. FS-11557 [mod_conference] Missed a spot where APP_SESSION_ID needed to be set. FS-11557: set session id for outbound (initial requests) FS-11557: [mod_sofia] rename vars and functions "session id" -> "session uuid" to reflect the real meaning for rfc7989. FS-11557: fix bug - colliding chan var names (session_id) FS-11557: check nil session uuid FS-11557 : replace CS_NEW with CS_INIT for when originating calls, generate new uuid. FS-11557: handle inbound (UAS mode, one leg) FS-11557: generic param handling and filter via new sip profile option "rfc-7989-filter", eg: <param name="rfc-7989-filter" value="logme, sec-agree, privacy" /> FS-11557: renamed chan vars (reflect meaning only for RFC7989) FS-11557: fallback to RFC7329 - "old" Session-ID FS-11557: distinguish between request and replies when we read the header (to provide compatibility with old RFC7329 - section 11 of RFC7989) FS-11557: change more vars/consts names FS-11557: move compat flag on the channel. FS-11557: add Session-ID header in REFER FS-11557: needs extra condition on received initial request FS-11557: handle NOTIFY FS-11557: support answer() in dialplan - it was sending back a 200 OK with Session-ID invalid, eg: A=NIL;B=X FS-11557: add Session-ID for NOTIFY (more cases) FS-11557: handle reply to SIP INFO (add Session-ID header) FS-11557: handle case of BYE after REFER, when the channel is destroyed already (save the uuid on sofia_private) FS-11557: handle more SIP reply cases (eg: 202 Accepted , more negative replies) FS-11557: handle ACK (UAS role) FS-11557: added "rfc-7989-force-old" profile param - to enforce old rfc7329 for the UAC role. default off. enabled with "<param name="rfc-7989-force-old" value="true" />". FS-11557: fallback to rfc7329 fixes. FS-11557: set flag CF_RFC7329_COMPAT on partner channel where needed FS-11557: fix crash (mod_conference)
2018-12-05 22:58:25 +00:00
TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)), TAG_IF(!zstr(subject), SIPTAG_SUBJECT_STR(subject)),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
2012-08-31 20:35:13 +00:00
}
switch_core_session_rwunlock(session);
}
}
}
break;
case SWITCH_EVENT_SEND_INFO:
{
const char *profile_name = switch_event_get_header(event, "profile");
const char *ct = switch_event_get_header(event, "content-type");
const char *cd = switch_event_get_header(event, "content-disposition");
const char *to_uri = switch_event_get_header(event, "to-uri");
const char *local_user_full = switch_event_get_header(event, "local-user");
const char *from_uri = switch_event_get_header(event, "from-uri");
const char *call_info = switch_event_get_header(event, "call-info");
const char *alert_info = switch_event_get_header(event, "alert-info");
const char *call_id = switch_event_get_header(event, "call-id");
const char *body = switch_event_get_body(event);
sofia_profile_t *profile = NULL;
nua_handle_t *nh;
char *local_dup = NULL;
char *local_user, *local_host;
char buf[1024] = "";
char *p;
if (!profile_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Profile Name\n");
goto done;
}
if (!call_id && !to_uri && !local_user_full) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing To-URI header\n");
goto done;
}
if (!call_id && !from_uri) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing From-URI header\n");
goto done;
}
if (!(profile = sofia_glue_find_profile(profile_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find profile %s\n", profile_name);
goto done;
}
if (call_id) {
nh = nua_handle_by_call_id(profile->nua, call_id);
if (!nh) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Call-ID %s\n", call_id);
goto done;
}
} else {
if (local_user_full) {
local_dup = strdup(local_user_full);
switch_assert(local_dup);
local_user = local_dup;
if ((local_host = strchr(local_user, '@'))) {
*local_host++ = '\0';
}
if (!local_host || !sofia_reg_find_reg_url(profile, local_user, local_host, buf, sizeof(buf))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find local user\n");
goto done;
}
to_uri = sofia_glue_get_url_from_contact(buf, 0);
if ((p = strstr(to_uri, ";fs_"))) {
*p = '\0';
}
}
nh = nua_handle(profile->nua,
NULL, NUTAG_URL(to_uri), SIPTAG_FROM_STR(from_uri), SIPTAG_TO_STR(to_uri), SIPTAG_CONTACT_STR(profile->url), TAG_END());
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
}
nua_info(nh,
TAG_IF(ct, SIPTAG_CONTENT_TYPE_STR(ct)),
TAG_IF(cd, SIPTAG_CONTENT_DISPOSITION_STR(cd)),
TAG_IF(alert_info, SIPTAG_ALERT_INFO_STR(alert_info)),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)), TAG_END());
if (call_id && nh) {
nua_handle_unref(nh);
}
sofia_glue_release_profile(profile);
2010-06-30 15:35:03 +00:00
done:
switch_safe_free(local_dup);
}
break;
case SWITCH_EVENT_TRAP:
{
const char *cond = switch_event_get_header(event, "condition");
switch_hash_index_t *hi;
const void *var;
void *val;
sofia_profile_t *profile;
if (zstr(cond)) {
cond = "";
}
if (!strcmp(cond, "network-external-address-change") && mod_sofia_globals.auto_restart) {
const char *old_ip4 = switch_event_get_header_nil(event, "network-external-address-previous-v4");
const char *new_ip4 = switch_event_get_header_nil(event, "network-external-address-change-v4");
switch_mutex_lock(mod_sofia_globals.hash_mutex);
if (mod_sofia_globals.profile_hash && !zstr(old_ip4) && !zstr(new_ip4)) {
2014-04-01 22:21:29 +00:00
for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
switch_core_hash_this(hi, &var, NULL, &val);
if ((profile = (sofia_profile_t *) val)) {
if (!zstr(profile->extsipip) && !strcmp(profile->extsipip, old_ip4)) {
profile->extsipip = switch_core_strdup(profile->pool, new_ip4);
}
if (!zstr(profile->extrtpip) && !strcmp(profile->extrtpip, old_ip4)) {
profile->extrtpip = switch_core_strdup(profile->pool, new_ip4);
}
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
sofia_glue_restart_all_profiles();
} else if (!strcmp(cond, "network-address-change") && mod_sofia_globals.auto_restart) {
const char *old_ip4 = switch_event_get_header_nil(event, "network-address-previous-v4");
const char *new_ip4 = switch_event_get_header_nil(event, "network-address-change-v4");
const char *old_ip6 = switch_event_get_header_nil(event, "network-address-previous-v6");
const char *new_ip6 = switch_event_get_header_nil(event, "network-address-change-v6");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "EVENT_TRAP: IP change detected\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "IP change detected [%s]->[%s] [%s]->[%s]\n", old_ip4, new_ip4, old_ip6, new_ip6);
2019-06-19 19:53:35 +00:00
snprintf(mod_sofia_globals.guess_ip, sizeof(mod_sofia_globals.guess_ip), "%s", new_ip4);
2011-06-15 15:29:44 +00:00
switch_mutex_lock(mod_sofia_globals.hash_mutex);
if (mod_sofia_globals.profile_hash) {
2014-04-01 22:21:29 +00:00
for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
int rb = 0;
uint32_t x = 0;
switch_core_hash_this(hi, &var, NULL, &val);
if ((profile = (sofia_profile_t *) val) && profile->auto_restart) {
if (!strcmp(profile->sipip, old_ip4)) {
profile->sipip = switch_core_strdup(profile->pool, new_ip4);
rb++;
}
2010-06-23 18:22:52 +00:00
for (x = 0; x < profile->rtpip_index; x++) {
if (!strcmp(profile->rtpip[x], old_ip4)) {
profile->rtpip[x] = switch_core_strdup(profile->pool, new_ip4);
rb++;
}
if (!strcmp(profile->rtpip[x], old_ip6)) {
profile->rtpip6[x] = switch_core_strdup(profile->pool, new_ip6);
rb++;
}
}
2010-06-23 18:22:52 +00:00
if (!strcmp(profile->sipip, old_ip6)) {
profile->sipip = switch_core_strdup(profile->pool, new_ip6);
rb++;
}
2010-06-23 18:22:52 +00:00
if (rb) {
sofia_set_pflag_locked(profile, PFLAG_RESPAWN);
sofia_clear_pflag_locked(profile, PFLAG_RUNNING);
}
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
}
break;
default:
break;
}
}
2016-02-17 22:22:46 +00:00
static void general_queue_event_handler(switch_event_t *event)
{
switch_event_t *dup;
switch_event_dup(&dup, event);
switch_queue_push(mod_sofia_globals.general_event_queue, dup);
}
void write_csta_xml_chunk(switch_event_t *event, switch_stream_handle_t stream, const char *csta_event, char *fwdtype)
{
const char *device = switch_event_get_header(event, "device");
switch_assert(csta_event);
stream.write_function(&stream, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<%s xmlns=\"http://www.ecma-international.org/standards/ecma-323/csta/ed3\">\n", csta_event);
if (device) {
stream.write_function(&stream, " <device>%s</device>\n", device);
}
if (!strcmp(csta_event, "DoNotDisturbEvent")) {
const char *dndstatus = switch_event_get_header(event, "doNotDisturbOn");
if (dndstatus) {
stream.write_function(&stream, " <doNotDisturbOn>%s</doNotDisturbOn>\n", dndstatus);
}
} else if(!strcmp(csta_event, "ForwardingEvent")) {
const char *fwdstatus = NULL;
const char *fwdto = NULL;
const char *ringcount = NULL;
if (fwdtype && !zstr(fwdtype)) {
if (!strcmp("forwardImmediate", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_immediate");
fwdstatus = switch_event_get_header(event, "forward_immediate_enabled");
} else if (!strcmp("forwardBusy", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_busy");
fwdstatus = switch_event_get_header(event, "forward_busy_enabled");
} else if (!strcmp("forwardNoAns", fwdtype)) {
fwdto = switch_event_get_header(event, "forward_no_answer");
fwdstatus = switch_event_get_header(event, "forward_no_answer_enabled");
ringcount = switch_event_get_header(event, "ringCount");
}
stream.write_function(&stream, " <forwardingType>%s</forwardingType>\n", fwdtype);
if (fwdstatus) {
stream.write_function(&stream, " <forwardStatus>%s</forwardStatus>\n", fwdstatus);
}
if (fwdto) {
stream.write_function(&stream, " <forwardTo>%s</forwardTo>\n", fwdto);
}
if (ringcount) {
stream.write_function(&stream, " <ringCount>%s</ringCount>\n", ringcount);
}
}
}
stream.write_function(&stream, "</%s>\n", csta_event);
}
switch_status_t list_profiles_full(const char *line, const char *cursor, switch_console_callback_match_t **matches, switch_bool_t show_aliases)
{
sofia_profile_t *profile = NULL;
switch_hash_index_t *hi;
void *val;
const void *vvar;
switch_console_callback_match_t *my_matches = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
2014-04-01 22:21:29 +00:00
for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
switch_core_hash_this(hi, &vvar, NULL, &val);
profile = (sofia_profile_t *) val;
if (!show_aliases && strcmp((char *)vvar, profile->name)) {
continue;
}
if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
switch_console_push_match(&my_matches, (const char *) vvar);
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
if (my_matches) {
*matches = my_matches;
status = SWITCH_STATUS_SUCCESS;
}
return status;
}
switch_status_t list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
return list_profiles_full(line, cursor, matches, SWITCH_TRUE);
}
static switch_status_t list_gateways(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
sofia_profile_t *profile = NULL;
switch_hash_index_t *hi;
void *val;
const void *vvar;
switch_console_callback_match_t *my_matches = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
2014-04-01 22:21:29 +00:00
for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
switch_core_hash_this(hi, &vvar, NULL, &val);
profile = (sofia_profile_t *) val;
if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
sofia_gateway_t *gp;
switch_mutex_lock(profile->gw_mutex);
for (gp = profile->gateways; gp; gp = gp->next) {
switch_console_push_match(&my_matches, gp->name);
}
switch_mutex_unlock(profile->gw_mutex);
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
if (my_matches) {
*matches = my_matches;
status = SWITCH_STATUS_SUCCESS;
}
return status;
}
static switch_status_t list_profile_gateway(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
sofia_profile_t *profile = NULL;
switch_console_callback_match_t *my_matches = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
char *dup = NULL;
2011-04-22 21:43:29 +00:00
//int argc;
char *argv[4] = { 0 };
if (zstr(line)) {
return SWITCH_STATUS_FALSE;
}
dup = strdup(line);
2011-04-22 21:43:29 +00:00
switch_split(dup, ' ', argv);
if (zstr(argv[2]) || !strcmp(argv[2], " ")) {
goto end;
}
if ((profile = sofia_glue_find_profile(argv[2]))) {
sofia_gateway_t *gp;
for (gp = profile->gateways; gp; gp = gp->next) {
switch_console_push_match(&my_matches, gp->name);
}
sofia_glue_release_profile(profile);
}
if (my_matches) {
*matches = my_matches;
status = SWITCH_STATUS_SUCCESS;
}
2010-06-30 15:35:03 +00:00
end:
switch_safe_free(dup);
return status;
}
SWITCH_STANDARD_APP(sofia_sla_function)
{
private_object_t *tech_pvt;
switch_core_session_t *bargee_session;
switch_channel_t *channel = switch_core_session_get_channel(session);
if (zstr(data)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: <uuid>\n");
return;
}
switch_channel_answer(channel);
if ((bargee_session = switch_core_session_locate((char *)data))) {
if (bargee_session == session) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "BARGE: %s (cannot barge on myself)\n", (char *) data);
} else {
if (switch_core_session_check_interface(bargee_session, sofia_endpoint_interface)) {
tech_pvt = switch_core_session_get_private(bargee_session);
2012-12-21 04:57:47 +00:00
switch_channel_clear_flag(tech_pvt->channel, CF_SLA_BARGING);
switch_channel_set_flag(tech_pvt->channel, CF_SLA_BARGE);
switch_ivr_transfer_variable(bargee_session, session, SWITCH_SIGNAL_BOND_VARIABLE);
}
2012-05-11 03:34:37 +00:00
if (switch_core_session_check_interface(session, sofia_endpoint_interface)) {
tech_pvt = switch_core_session_get_private(session);
2012-12-21 04:57:47 +00:00
switch_channel_set_flag(tech_pvt->channel, CF_SLA_BARGING);
2012-05-11 03:34:37 +00:00
}
2012-05-11 03:34:37 +00:00
switch_channel_set_variable(channel, "sip_barging_uuid", (char *)data);
}
switch_core_session_rwunlock(bargee_session);
}
switch_channel_execute_on(channel, "execute_on_sip_barge");
switch_ivr_eavesdrop_session(session, data, NULL, ED_MUX_READ | ED_MUX_WRITE | ED_COPY_DISPLAY);
}
SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
{
switch_chat_interface_t *chat_interface;
switch_api_interface_t *api_interface;
switch_management_interface_t *management_interface;
switch_application_interface_t *app_interface;
struct in_addr in;
switch_status_t status;
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
memset(&mod_sofia_globals, 0, sizeof(mod_sofia_globals));
mod_sofia_globals.destroy_private.destroy_nh = 1;
mod_sofia_globals.destroy_private.is_static = 1;
mod_sofia_globals.keep_private.is_static = 1;
mod_sofia_globals.pool = pool;
switch_mutex_init(&mod_sofia_globals.mutex, SWITCH_MUTEX_NESTED, mod_sofia_globals.pool);
switch_core_hash_init(&mod_sofia_globals.profile_hash);
switch_core_hash_init(&mod_sofia_globals.gateway_hash);
switch_mutex_init(&mod_sofia_globals.hash_mutex, SWITCH_MUTEX_NESTED, mod_sofia_globals.pool);
if (switch_event_reserve_subclass(MY_EVENT_NOTIFY_REFER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_NOTIFY_REFER);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_NOTIFY_WATCHED_HEADER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_NOTIFY_WATCHED_HEADER);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_UNREGISTER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_UNREGISTER);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_PROFILE_START) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_PROFILE_START);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_REINVITE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REINVITE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_REPLACED) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REPLACED);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_TRANSFEROR) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_TRANSFEROR);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_TRANSFEREE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_TRANSFEREE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_ERROR) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_ERROR);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_INTERCEPTED) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_INTERCEPTED);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_STATE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_STATE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_SIP_USER_STATE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_SIP_USER_STATE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_DEL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_DEL);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_EXPIRE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_EXPIRE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_REGISTER_ATTEMPT) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER_ATTEMPT);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_REGISTER_FAILURE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER_FAILURE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_PRE_REGISTER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_PRE_REGISTER);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_REGISTER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_ADD) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_ADD);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_BYE_RESPONSE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_BYE_RESPONSE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
switch_find_local_ip(mod_sofia_globals.guess_ip, sizeof(mod_sofia_globals.guess_ip), &mod_sofia_globals.guess_mask, AF_INET);
in.s_addr = mod_sofia_globals.guess_mask;
switch_set_string(mod_sofia_globals.guess_mask_str, inet_ntoa(in));
strcpy(mod_sofia_globals.hostname, switch_core_get_switchname());
switch_mutex_lock(mod_sofia_globals.mutex);
mod_sofia_globals.running = 1;
switch_mutex_unlock(mod_sofia_globals.mutex);
mod_sofia_globals.auto_nat = (switch_nat_get_type() ? 1 : 0);
switch_queue_create(&mod_sofia_globals.presence_queue, SOFIA_QUEUE_SIZE, mod_sofia_globals.pool);
2016-02-17 22:22:46 +00:00
switch_queue_create(&mod_sofia_globals.general_event_queue, SOFIA_QUEUE_SIZE, mod_sofia_globals.pool);
2012-05-03 21:31:21 +00:00
mod_sofia_globals.cpu_count = switch_core_cpu_count();
mod_sofia_globals.max_msg_queues = (mod_sofia_globals.cpu_count / 2) + 1;
if (mod_sofia_globals.max_msg_queues < 2) {
mod_sofia_globals.max_msg_queues = 2;
}
2012-05-03 21:31:21 +00:00
if (mod_sofia_globals.max_msg_queues > SOFIA_MAX_MSG_QUEUE) {
mod_sofia_globals.max_msg_queues = SOFIA_MAX_MSG_QUEUE;
}
switch_queue_create(&mod_sofia_globals.msg_queue, SOFIA_MSG_QUEUE_SIZE * mod_sofia_globals.max_msg_queues, mod_sofia_globals.pool);
2012-05-03 21:31:21 +00:00
/* start one message thread */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Starting initial message thread.\n");
if (sofia_init() != SWITCH_STATUS_SUCCESS) {
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (config_sofia(SOFIA_CONFIG_LOAD, NULL) != SWITCH_STATUS_SUCCESS) {
mod_sofia_globals.running = 0;
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
sofia_msg_thread_start(0);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for profiles to start\n");
switch_yield(1500000);
2012-07-11 20:15:43 +00:00
if (switch_event_bind(modname, SWITCH_EVENT_CUSTOM, MULTICAST_EVENT, event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_TERM, err);
}
2012-07-11 20:15:43 +00:00
if (switch_event_bind(modname, SWITCH_EVENT_CONFERENCE_DATA, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
2012-07-11 20:15:43 +00:00
if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_IN, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
2012-07-11 20:15:43 +00:00
if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_OUT, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
2012-07-11 20:15:43 +00:00
if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
2012-07-11 20:15:43 +00:00
if (switch_event_bind(modname, SWITCH_EVENT_ROSTER, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_MESSAGE_WAITING, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
2012-07-11 20:15:43 +00:00
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
2012-07-11 20:15:43 +00:00
return SWITCH_STATUS_GENERR;
}
2016-02-17 22:22:46 +00:00
if (switch_event_bind(modname, SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, general_queue_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
2016-02-17 22:22:46 +00:00
if (switch_event_bind(modname, SWITCH_EVENT_NOTIFY, SWITCH_EVENT_SUBCLASS_ANY, general_queue_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
2016-02-17 22:22:46 +00:00
if (switch_event_bind(modname, SWITCH_EVENT_PHONE_FEATURE, SWITCH_EVENT_SUBCLASS_ANY, general_queue_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
2016-02-17 22:22:46 +00:00
if (switch_event_bind(modname, SWITCH_EVENT_SEND_MESSAGE, SWITCH_EVENT_SUBCLASS_ANY, general_queue_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
2016-02-17 22:22:46 +00:00
if (switch_event_bind(modname, SWITCH_EVENT_SEND_INFO, SWITCH_EVENT_SUBCLASS_ANY, general_queue_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
sofia_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
sofia_endpoint_interface->interface_name = "sofia";
sofia_endpoint_interface->io_routines = &sofia_io_routines;
sofia_endpoint_interface->state_handler = &sofia_event_handlers;
sofia_endpoint_interface->recover_callback = sofia_recover_callback;
management_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_MANAGEMENT_INTERFACE);
management_interface->relative_oid = "1001";
management_interface->management_function = sofia_manage;
add_sofia_json_apis(module_interface);
SWITCH_ADD_APP(app_interface, "sofia_sla", "private sofia sla function",
"private sofia sla function", sofia_sla_function, "<uuid>", SAF_NONE);
SWITCH_ADD_API(api_interface, "sofia", "Sofia Controls", sofia_function, "<cmd> <args>");
SWITCH_ADD_API(api_interface, "sofia_gateway_data", "Get data from a sofia gateway", sofia_gateway_data_function, "<gateway_name> [ivar|ovar|var] <name>");
switch_console_set_complete("add sofia ::[help:status");
switch_console_set_complete("add sofia status profile ::sofia::list_profiles reg");
switch_console_set_complete("add sofia status gateway ::sofia::list_gateways");
switch_console_set_complete("add sofia loglevel ::[all:default:tport:iptsec:nea:nta:nth_client:nth_server:nua:soa:sresolv:stun ::[0:1:2:3:4:5:6:7:8:9");
switch_console_set_complete("add sofia tracelevel ::[console:alert:crit:err:warning:notice:info:debug");
switch_console_set_complete("add sofia global ::[siptrace::standby::capture::watchdog ::[on:off");
switch_console_set_complete("add sofia global debug ::[presence:sla:none");
switch_console_set_complete("add sofia profile restart all");
switch_console_set_complete("add sofia profile ::sofia::list_profiles ::[start:rescan:restart:check_sync");
switch_console_set_complete("add sofia profile ::sofia::list_profiles stop wait");
switch_console_set_complete("add sofia profile ::sofia::list_profiles flush_inbound_reg reboot");
switch_console_set_complete("add sofia profile ::sofia::list_profiles ::[register:unregister all");
switch_console_set_complete("add sofia profile ::sofia::list_profiles ::[register:unregister:killgw:startgw ::sofia::list_profile_gateway");
switch_console_set_complete("add sofia profile ::sofia::list_profiles killgw _all_");
switch_console_set_complete("add sofia profile ::sofia::list_profiles startgw _all_");
switch_console_set_complete("add sofia profile ::sofia::list_profiles ::[siptrace:capture:watchdog ::[on:off");
switch_console_set_complete("add sofia profile ::sofia::list_profiles gwlist ::[up:down");
switch_console_set_complete("add sofia recover flush");
switch_console_set_complete("add sofia xmlstatus profile ::sofia::list_profiles reg");
switch_console_set_complete("add sofia xmlstatus gateway ::sofia::list_gateways");
switch_console_add_complete_func("::sofia::list_profiles", list_profiles);
switch_console_add_complete_func("::sofia::list_gateways", list_gateways);
switch_console_add_complete_func("::sofia::list_profile_gateway", list_profile_gateway);
2011-03-25 21:35:30 +00:00
SWITCH_ADD_API(api_interface, "sofia_username_of", "Sofia Username Lookup", sofia_username_of_function, "[profile/]<user>@<domain>");
SWITCH_ADD_API(api_interface, "sofia_contact", "Sofia Contacts", sofia_contact_function, "[profile/]<user>@<domain>");
SWITCH_ADD_API(api_interface, "sofia_count_reg", "Count Sofia registration", sofia_count_reg_function, "[profile/]<user>@<domain>");
SWITCH_ADD_API(api_interface, "sofia_dig", "SIP DIG", sip_dig_function, "<url>");
2013-04-17 20:38:37 +00:00
SWITCH_ADD_API(api_interface, "sofia_presence_data", "Sofia Presence Data", sofia_presence_data_function, "[list|status|rpid|user_agent] [profile/]<user>@domain");
SWITCH_ADD_CHAT(chat_interface, SOFIA_CHAT_PROTO, sofia_presence_chat_send);
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
crtp_init(*module_interface);
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
err:
mod_sofia_shutdown_cleanup();
return status;
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
}
void mod_sofia_shutdown_cleanup() {
int sanity = 0;
int i;
2013-02-18 18:58:33 +00:00
switch_status_t st;
switch_event_free_subclass(MY_EVENT_NOTIFY_REFER);
switch_event_free_subclass(MY_EVENT_NOTIFY_WATCHED_HEADER);
switch_event_free_subclass(MY_EVENT_UNREGISTER);
switch_event_free_subclass(MY_EVENT_PROFILE_START);
switch_event_free_subclass(MY_EVENT_REINVITE);
switch_event_free_subclass(MY_EVENT_REPLACED);
switch_event_free_subclass(MY_EVENT_TRANSFEROR);
switch_event_free_subclass(MY_EVENT_TRANSFEREE);
switch_event_free_subclass(MY_EVENT_ERROR);
switch_event_free_subclass(MY_EVENT_INTERCEPTED);
switch_event_free_subclass(MY_EVENT_GATEWAY_STATE);
switch_event_free_subclass(MY_EVENT_SIP_USER_STATE);
switch_event_free_subclass(MY_EVENT_GATEWAY_DEL);
switch_event_free_subclass(MY_EVENT_EXPIRE);
switch_event_free_subclass(MY_EVENT_REGISTER_ATTEMPT);
switch_event_free_subclass(MY_EVENT_REGISTER_FAILURE);
switch_event_free_subclass(MY_EVENT_PRE_REGISTER);
switch_event_free_subclass(MY_EVENT_REGISTER);
switch_event_free_subclass(MY_EVENT_GATEWAY_ADD);
2016-12-07 14:41:45 +00:00
switch_event_free_subclass(MY_EVENT_BYE_RESPONSE);
switch_console_del_complete_func("::sofia::list_profiles");
switch_console_set_complete("del sofia");
switch_mutex_lock(mod_sofia_globals.mutex);
if (mod_sofia_globals.running == 1) {
mod_sofia_globals.running = 0;
}
switch_mutex_unlock(mod_sofia_globals.mutex);
2012-07-11 20:15:43 +00:00
switch_event_unbind_callback(sofia_presence_event_handler);
2016-02-17 22:22:46 +00:00
switch_event_unbind_callback(general_queue_event_handler);
2012-07-11 20:15:43 +00:00
switch_event_unbind_callback(event_handler);
if (mod_sofia_globals.presence_queue) {
switch_queue_push(mod_sofia_globals.presence_queue, NULL);
switch_queue_interrupt_all(mod_sofia_globals.presence_queue);
}
while (mod_sofia_globals.threads) {
switch_cond_next();
if (++sanity >= 60000) {
break;
}
}
for (i = 0; mod_sofia_globals.msg_queue_thread[i]; i++) {
switch_queue_push(mod_sofia_globals.msg_queue, NULL);
2013-02-18 18:58:33 +00:00
switch_queue_interrupt_all(mod_sofia_globals.msg_queue);
2011-06-20 15:07:01 +00:00
}
for (i = 0; mod_sofia_globals.msg_queue_thread[i]; i++) {
switch_thread_join(&st, mod_sofia_globals.msg_queue_thread[i]);
}
2013-02-18 18:58:33 +00:00
if (mod_sofia_globals.presence_thread) {
switch_thread_join(&st, mod_sofia_globals.presence_thread);
}
2011-06-20 15:07:01 +00:00
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
su_deinit();
/*
Release the clone of the default SIP parser
created by `sip_update_default_mclass(sip_extend_mclass(NULL))` call with NULL argument
*/
sip_cloned_parser_destroy();
switch_mutex_lock(mod_sofia_globals.hash_mutex);
switch_core_hash_destroy(&mod_sofia_globals.profile_hash);
switch_core_hash_destroy(&mod_sofia_globals.gateway_hash);
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)
{
mod_sofia_shutdown_cleanup();
Adding mod_sofia to the tree so we can work on it easier.... I am not adding it to the examples or to the modules.conf because it's not really ready for that yet. This is only 1.5 days old from scratch at this point but the brave hearted who want to play with it can do the following: Add this to modules.conf: ----------------------------------------------------------------------------- endpoints/mod_sofia ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration/modules.conf area ----------------------------------------------------------------------------- <load module="mod_sofia"/> ----------------------------------------------------------------------------- Add this to freeswitch.xml in the configuration section ----------------------------------------------------------------------------- <configuration name="sofia.conf" description="sofia Endpoint"> <!-- You may have multiple profiles --> <profile name="test"> <param name="rfc2833-pt" value="101"/> <param name="sip-port" value="5060"/> <param name="dialplan" value="XML"/> <param name="dtmf-duration" value="100"/> <param name="codec-prefs" value="PCMU"/> <param name="use-rtp-timer" value="true"/> <param name="rtp-ip" value="127.0.0.1"/> <param name="sip-ip" value="127.0.0.1"/> <!-- optional ; --> <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>--> <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> --> <!-- VAD choose one (out is a good choice); --> <!-- <param name="vad" value="in"/> --> <!-- <param name="vad" value="out"/> --> <!-- <param name="vad" value="both"/> --> <!--<param name="alias" value="sip:208.64.200.40:5555"/>--> </profile> </configuration> ----------------------------------------------------------------------------- The call string to use profile test would be: sofia/test/1000@1.2.3.4 as in: <action application="bridge" data="sofia/test/1000@1.2.3.4"/> git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2398 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-08-25 23:55:59 +00:00
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/