2006-08-25 23:55:59 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
* Copyright ( C ) 2005 / 2006 , Anthony Minessale II < anthmct @ yahoo . com >
*
* 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 < anthmct @ yahoo . com >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Anthony Minessale II < anthmct @ yahoo . com >
2006-10-18 22:57:35 +00:00
* Ken Rice , Asteria Solutions Group , Inc < ken @ asteriasgi . com >
2006-10-24 22:11:25 +00:00
* Paul D . Tinsley < pdt at jackhammer . org >
2007-02-25 21:00:26 +00:00
* Bret McDanel < trixter AT 0xdecafbad . com >
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*/
/*************************************************************************************************************************************************************/
/*Defines etc..*/
/*************************************************************************************************************************************************************/
# define HAVE_APR
# include <switch.h>
2007-03-29 22:31:56 +00:00
static const switch_state_handler_table_t noop_state_handler = { 0 } ;
2006-09-30 00:00:07 +00:00
struct outbound_reg ;
typedef struct outbound_reg outbound_reg_t ;
2006-08-25 23:55:59 +00:00
struct sofia_profile ;
typedef struct sofia_profile sofia_profile_t ;
# define NUA_MAGIC_T sofia_profile_t
2006-09-30 00:00:07 +00:00
struct sofia_private {
2007-03-29 22:31:56 +00:00
char uuid [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] ;
2007-03-19 21:09:53 +00:00
outbound_reg_t * gateway ;
2006-09-30 00:00:07 +00:00
} ;
typedef struct sofia_private sofia_private_t ;
2006-08-25 23:55:59 +00:00
struct private_object ;
typedef struct private_object private_object_t ;
2006-09-30 00:00:07 +00:00
# define NUA_HMAGIC_T sofia_private_t
2006-08-25 23:55:59 +00:00
# define MY_EVENT_REGISTER "sofia::register"
# define MY_EVENT_EXPIRE "sofia::expire"
2006-09-27 20:18:14 +00:00
# define MULTICAST_EVENT "multicast::event"
2006-10-05 14:24:25 +00:00
# define SOFIA_REPLACES_HEADER "_sofia_replaces_"
2006-10-10 03:19:59 +00:00
# define SOFIA_USER_AGENT "FreeSWITCH(mod_sofia)"
2006-10-20 22:11:26 +00:00
# define SOFIA_CHAT_PROTO "sip"
2007-02-13 01:22:17 +00:00
# define SOFIA_SIP_HEADER_PREFIX "sip_h_"
# define SOFIA_SIP_HEADER_PREFIX_T "~sip_h_"
2007-03-19 21:09:53 +00:00
# define SOFIA_DEFAULT_PORT "5060"
2006-10-06 22:39:49 +00:00
2006-08-25 23:55:59 +00:00
# include <sofia-sip/nua.h>
# include <sofia-sip/sip_status.h>
# include <sofia-sip/sdp.h>
2006-08-28 16:40:05 +00:00
# include <sofia-sip/sip_protos.h>
2006-09-28 21:21:44 +00:00
# include <sofia-sip/auth_module.h>
# include <sofia-sip/su_md5.h>
2006-10-09 17:11:39 +00:00
# include <sofia-sip/su_log.h>
2006-10-15 05:10:34 +00:00
# include <sofia-sip/nea.h>
2007-02-08 20:16:08 +00:00
# include <sofia-sip/msg_addr.h>
2006-09-27 03:44:14 +00:00
2006-10-15 05:20:49 +00:00
extern su_log_t tport_log [ ] ;
2006-10-31 21:46:42 +00:00
static switch_frame_t silence_frame = { 0 } ;
2006-10-31 21:38:06 +00:00
static char silence_data [ 13 ] = " " ;
2006-09-27 03:44:14 +00:00
static char reg_sql [ ] =
2007-03-29 22:31:56 +00:00
" CREATE TABLE sip_registrations ( \n "
" user VARCHAR(255), \n "
" host VARCHAR(255), \n "
2007-03-30 00:13:31 +00:00
" contact VARCHAR(1024), \n " " status VARCHAR(255), \n " " rpid VARCHAR(255), \n " " expires INTEGER(8) " " ); \n " ;
2006-09-27 03:44:14 +00:00
2006-10-15 05:10:34 +00:00
static char sub_sql [ ] =
2007-03-29 22:31:56 +00:00
" CREATE TABLE sip_subscriptions ( \n "
" proto VARCHAR(255), \n "
" user VARCHAR(255), \n "
" host VARCHAR(255), \n "
" sub_to_user VARCHAR(255), \n "
" sub_to_host VARCHAR(255), \n "
" event VARCHAR(255), \n "
" contact VARCHAR(1024), \n "
2007-03-30 00:13:31 +00:00
" call_id VARCHAR(255), \n " " full_from VARCHAR(255), \n " " full_via VARCHAR(255), \n " " expires INTEGER(8) " " ); \n " ;
2006-10-15 05:10:34 +00:00
2006-09-28 21:21:44 +00:00
static char auth_sql [ ] =
2007-03-29 22:31:56 +00:00
" CREATE TABLE sip_authentication ( \n "
" user VARCHAR(255), \n "
2007-03-30 00:13:31 +00:00
" host VARCHAR(255), \n " " passwd VARCHAR(255), \n " " nonce VARCHAR(255), \n " " expires INTEGER(8) " " ); \n " ;
2006-09-28 21:21:44 +00:00
2006-08-25 23:55:59 +00:00
static const char modname [ ] = " mod_sofia " ;
# define STRLEN 15
static switch_memory_pool_t * module_pool = NULL ;
# define set_param(ptr,val) if (ptr) {free(ptr) ; ptr = NULL;} if (val) {ptr = strdup(val);}
# define set_anchor(t,m) if (t->Anchor) {delete t->Anchor;} t->Anchor = new SipMessage(m);
/* Local Structures */
/*************************************************************************************************************************************************************/
struct sip_alias_node {
char * url ;
nua_t * nua ;
struct sip_alias_node * next ;
} ;
typedef struct sip_alias_node sip_alias_node_t ;
2006-09-29 01:07:51 +00:00
typedef enum {
PFLAG_AUTH_CALLS = ( 1 < < 0 ) ,
2006-09-29 18:12:31 +00:00
PFLAG_BLIND_REG = ( 1 < < 1 ) ,
PFLAG_AUTH_ALL = ( 1 < < 2 ) ,
2006-10-12 00:59:09 +00:00
PFLAG_FULL_ID = ( 1 < < 3 ) ,
2007-01-28 02:38:52 +00:00
PFLAG_PRESENCE = ( 1 < < 4 ) ,
2007-01-28 17:37:51 +00:00
PFLAG_PASS_RFC2833 = ( 1 < < 5 ) ,
2007-03-29 22:31:56 +00:00
PFLAG_DISABLE_TRANSCODING = ( 1 < < 6 )
2006-09-29 01:07:51 +00:00
} PFLAGS ;
2006-08-25 23:55:59 +00:00
typedef enum {
TFLAG_IO = ( 1 < < 0 ) ,
2006-11-10 08:13:01 +00:00
TFLAG_CHANGE_MEDIA = ( 1 < < 1 ) ,
2006-08-25 23:55:59 +00:00
TFLAG_OUTBOUND = ( 1 < < 2 ) ,
TFLAG_READING = ( 1 < < 3 ) ,
TFLAG_WRITING = ( 1 < < 4 ) ,
TFLAG_HUP = ( 1 < < 5 ) ,
TFLAG_RTP = ( 1 < < 6 ) ,
TFLAG_BYE = ( 1 < < 7 ) ,
TFLAG_ANS = ( 1 < < 8 ) ,
TFLAG_EARLY_MEDIA = ( 1 < < 9 ) ,
TFLAG_SECURE = ( 1 < < 10 ) ,
2007-03-29 22:31:56 +00:00
TFLAG_VAD_IN = ( 1 < < 11 ) ,
TFLAG_VAD_OUT = ( 1 < < 12 ) ,
TFLAG_VAD = ( 1 < < 13 ) ,
2006-08-25 23:55:59 +00:00
TFLAG_TIMER = ( 1 < < 14 ) ,
2006-09-30 19:17:35 +00:00
TFLAG_READY = ( 1 < < 15 ) ,
2006-10-03 04:08:30 +00:00
TFLAG_REINVITE = ( 1 < < 16 ) ,
2006-10-06 22:39:49 +00:00
TFLAG_REFER = ( 1 < < 17 ) ,
TFLAG_NOHUP = ( 1 < < 18 ) ,
TFLAG_XFER = ( 1 < < 19 ) ,
2006-10-12 20:37:08 +00:00
TFLAG_NOMEDIA = ( 1 < < 20 ) ,
2006-10-24 21:31:39 +00:00
TFLAG_BUGGY_2833 = ( 1 < < 21 ) ,
2006-12-29 00:57:08 +00:00
TFLAG_SIP_HOLD = ( 1 < < 22 ) ,
2007-01-20 18:51:57 +00:00
TFLAG_INB_NOMEDIA = ( 1 < < 23 ) ,
TFLAG_LATE_NEGOTIATION = ( 1 < < 24 )
2006-08-25 23:55:59 +00:00
} TFLAGS ;
static struct {
switch_hash_t * profile_hash ;
2007-03-19 21:09:53 +00:00
switch_hash_t * gateway_hash ;
2006-08-25 23:55:59 +00:00
switch_mutex_t * hash_mutex ;
uint32_t callid ;
2006-09-27 03:44:14 +00:00
int32_t running ;
switch_mutex_t * mutex ;
2007-03-29 22:31:56 +00:00
char guess_ip [ 80 ] ;
2006-08-25 23:55:59 +00:00
} globals ;
2006-09-30 00:00:07 +00:00
typedef enum {
REG_FLAG_AUTHED = ( 1 < < 0 ) ,
} reg_flags_t ;
typedef enum {
REG_STATE_UNREGED ,
REG_STATE_TRYING ,
REG_STATE_REGISTER ,
REG_STATE_REGED ,
REG_STATE_FAILED ,
REG_STATE_EXPIRED
} reg_state_t ;
struct outbound_reg {
2006-12-28 01:08:06 +00:00
sofia_private_t * sofia_private ;
2006-09-30 00:00:07 +00:00
nua_handle_t * nh ;
sofia_profile_t * profile ;
char * name ;
char * register_scheme ;
char * register_realm ;
char * register_username ;
char * register_password ;
char * register_from ;
2007-03-19 21:09:53 +00:00
char * register_contact ;
2006-09-30 00:00:07 +00:00
char * register_to ;
char * register_proxy ;
2007-03-20 23:09:35 +00:00
char * register_context ;
2006-09-30 00:00:07 +00:00
char * expires_str ;
uint32_t freq ;
time_t expires ;
time_t retry ;
uint32_t flags ;
reg_state_t state ;
switch_memory_pool_t * pool ;
struct outbound_reg * next ;
} ;
2006-10-12 00:59:09 +00:00
2006-08-25 23:55:59 +00:00
struct sofia_profile {
int debug ;
char * name ;
2006-09-27 03:44:14 +00:00
char * dbname ;
2006-08-25 23:55:59 +00:00
char * dialplan ;
char * context ;
char * extrtpip ;
char * rtpip ;
char * sipip ;
char * extsipip ;
char * username ;
char * url ;
2007-01-15 04:32:21 +00:00
char * bindurl ;
2006-08-29 01:27:23 +00:00
char * sipdomain ;
2006-09-12 22:23:45 +00:00
char * timer_name ;
2006-08-25 23:55:59 +00:00
int sip_port ;
char * codec_string ;
int running ;
int codec_ms ;
int dtmf_duration ;
unsigned int flags ;
2006-09-29 01:07:51 +00:00
unsigned int pflags ;
2006-08-25 23:55:59 +00:00
uint32_t max_calls ;
2007-03-29 22:31:56 +00:00
uint32_t nonce_ttl ;
2006-08-25 23:55:59 +00:00
nua_t * nua ;
switch_memory_pool_t * pool ;
su_root_t * s_root ;
sip_alias_node_t * aliases ;
switch_payload_t te ;
2007-03-07 18:34:22 +00:00
switch_payload_t cng_pt ;
2006-09-02 23:04:25 +00:00
uint32_t codec_flags ;
2006-09-30 00:00:07 +00:00
switch_mutex_t * ireg_mutex ;
2007-03-19 21:09:53 +00:00
switch_mutex_t * gateway_mutex ;
outbound_reg_t * gateways ;
2006-10-12 00:59:09 +00:00
su_home_t * home ;
2006-10-18 22:57:35 +00:00
switch_hash_t * profile_hash ;
switch_hash_t * chat_hash ;
2006-08-25 23:55:59 +00:00
} ;
struct private_object {
2006-12-28 01:08:06 +00:00
sofia_private_t * sofia_private ;
2006-08-25 23:55:59 +00:00
uint32_t flags ;
2006-10-31 05:42:40 +00:00
switch_payload_t agreed_pt ;
2006-08-25 23:55:59 +00:00
switch_core_session_t * session ;
switch_frame_t read_frame ;
2007-02-23 20:03:30 +00:00
char * codec_order [ SWITCH_MAX_CODECS ] ;
int codec_order_last ;
2006-08-25 23:55:59 +00:00
const switch_codec_implementation_t * codecs [ SWITCH_MAX_CODECS ] ;
int num_codecs ;
switch_codec_t read_codec ;
switch_codec_t write_codec ;
uint32_t codec_ms ;
switch_caller_profile_t * caller_profile ;
2007-03-06 01:19:41 +00:00
uint32_t timestamp_send ;
2006-12-18 21:40:04 +00:00
//int32_t timestamp_recv;
2006-08-25 23:55:59 +00:00
switch_rtp_t * rtp_session ;
int ssrc ;
2006-12-18 21:40:04 +00:00
//switch_time_t last_read;
2006-08-25 23:55:59 +00:00
sofia_profile_t * profile ;
char * local_sdp_audio_ip ;
switch_port_t local_sdp_audio_port ;
char * remote_sdp_audio_ip ;
switch_port_t remote_sdp_audio_port ;
char * adv_sdp_audio_ip ;
switch_port_t adv_sdp_audio_port ;
2006-10-31 21:38:06 +00:00
char * proxy_sdp_audio_ip ;
switch_port_t proxy_sdp_audio_port ;
2006-08-25 23:55:59 +00:00
char * from_uri ;
char * to_uri ;
char * from_address ;
char * to_address ;
char * callid ;
char * far_end_contact ;
char * contact_url ;
2006-10-05 04:06:07 +00:00
char * from_str ;
2006-08-25 23:55:59 +00:00
char * rm_encoding ;
2006-10-09 02:24:43 +00:00
char * rm_fmtp ;
char * fmtp_out ;
2006-08-25 23:55:59 +00:00
char * remote_sdp_str ;
char * local_sdp_str ;
char * dest ;
2007-02-13 01:22:17 +00:00
char * dest_to ;
2006-09-29 18:12:31 +00:00
char * key ;
2006-10-06 22:39:49 +00:00
char * xferto ;
char * kick ;
2006-10-12 20:37:08 +00:00
char * origin ;
2006-10-18 22:57:35 +00:00
char * hash_key ;
char * chat_from ;
char * chat_to ;
char * e_dest ;
2007-03-29 22:31:56 +00:00
char * call_id ;
2006-08-25 23:55:59 +00:00
unsigned long rm_rate ;
switch_payload_t pt ;
switch_mutex_t * flag_mutex ;
switch_payload_t te ;
2007-02-21 21:46:32 +00:00
switch_payload_t bte ;
2007-03-07 18:34:22 +00:00
switch_payload_t cng_pt ;
switch_payload_t bcng_pt ;
2006-08-25 23:55:59 +00:00
nua_handle_t * nh ;
2006-10-06 22:39:49 +00:00
nua_handle_t * nh2 ;
2006-08-28 16:40:05 +00:00
su_home_t * home ;
sip_contact_t * contact ;
2006-08-25 23:55:59 +00:00
} ;
/* Function Prototypes */
/*************************************************************************************************************************************************************/
static switch_status_t sofia_on_init ( switch_core_session_t * session ) ;
static switch_status_t sofia_on_hangup ( switch_core_session_t * session ) ;
static switch_status_t sofia_on_loopback ( switch_core_session_t * session ) ;
static switch_status_t sofia_on_transmit ( switch_core_session_t * session ) ;
2007-03-29 22:31:56 +00:00
static switch_call_cause_t sofia_outgoing_channel ( switch_core_session_t * session ,
2007-03-30 00:13:31 +00:00
switch_caller_profile_t * outbound_profile , switch_core_session_t * * new_session , switch_memory_pool_t * * pool ) ;
2006-08-25 23:55:59 +00:00
2007-03-30 00:13:31 +00:00
static switch_status_t sofia_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , int timeout , switch_io_flag_t flags , int stream_id ) ;
2006-08-25 23:55:59 +00:00
2007-03-30 00:13:31 +00:00
static switch_status_t sofia_write_frame ( switch_core_session_t * session , switch_frame_t * frame , int timeout , switch_io_flag_t flags , int stream_id ) ;
2006-08-25 23:55:59 +00:00
static switch_status_t config_sofia ( int reload ) ;
static switch_status_t sofia_kill_channel ( switch_core_session_t * session , int sig ) ;
2007-03-29 22:31:56 +00:00
static switch_status_t activate_rtp ( private_object_t * tech_pvt ) ;
2006-08-25 23:55:59 +00:00
2007-03-29 22:31:56 +00:00
static void deactivate_rtp ( private_object_t * tech_pvt ) ;
2006-08-25 23:55:59 +00:00
2007-03-29 22:31:56 +00:00
static void set_local_sdp ( private_object_t * tech_pvt , char * ip , uint32_t port , char * sr , int force ) ;
2006-08-25 23:55:59 +00:00
2007-03-29 22:31:56 +00:00
static void tech_set_codecs ( private_object_t * tech_pvt ) ;
2006-08-25 23:55:59 +00:00
2007-03-30 00:13:31 +00:00
static void attach_private ( switch_core_session_t * session , sofia_profile_t * profile , private_object_t * tech_pvt , const char * channame ) ;
2006-08-25 23:55:59 +00:00
2006-08-26 21:13:56 +00:00
static void terminate_session ( switch_core_session_t * * session , switch_call_cause_t cause , int line ) ;
2006-08-25 23:55:59 +00:00
2007-03-29 22:31:56 +00:00
static switch_status_t tech_choose_port ( private_object_t * tech_pvt ) ;
2006-08-25 23:55:59 +00:00
2007-03-01 16:11:08 +00:00
static switch_status_t do_invite ( switch_core_session_t * session ) ;
2006-08-25 23:55:59 +00:00
2007-03-29 22:31:56 +00:00
static uint8_t negotiate_sdp ( switch_core_session_t * session , sdp_session_t * sdp ) ;
2006-08-25 23:55:59 +00:00
2007-03-30 00:13:31 +00:00
static char * get_auth_data ( char * dbname , char * nonce , char * npassword , size_t len , switch_mutex_t * mutex ) ;
2006-09-29 18:12:31 +00:00
2007-03-29 22:31:56 +00:00
static void establish_presence ( sofia_profile_t * profile ) ;
2006-10-20 22:11:26 +00:00
2006-08-25 23:55:59 +00:00
static void sip_i_state ( int status ,
2007-03-29 22:31:56 +00:00
char const * phrase ,
2007-03-30 00:13:31 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] ) ;
2007-03-29 22:31:56 +00:00
2007-03-30 00:13:31 +00:00
static void sip_i_refer ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , switch_core_session_t * session , sip_t const * sip , tagi_t tags [ ] ) ;
2007-03-29 22:31:56 +00:00
2007-03-30 00:13:31 +00:00
static void sip_i_info ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , switch_core_session_t * session , sip_t const * sip , tagi_t tags [ ] ) ;
2007-03-29 22:31:56 +00:00
2007-03-30 00:13:31 +00:00
static void sip_i_invite ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] ) ;
2007-03-29 22:31:56 +00:00
2007-03-30 00:13:31 +00:00
static void sip_i_register ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] ) ;
2007-03-29 22:31:56 +00:00
static void event_callback ( nua_event_t event ,
int status ,
char const * phrase ,
2007-03-30 00:13:31 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] ) ;
2006-08-25 23:55:59 +00:00
2007-03-30 00:13:31 +00:00
static void * SWITCH_THREAD_FUNC profile_thread_run ( switch_thread_t * thread , void * obj ) ;
2006-08-25 23:55:59 +00:00
2007-03-29 22:31:56 +00:00
static void launch_profile_thread ( sofia_profile_t * profile ) ;
2006-08-25 23:55:59 +00:00
2006-10-20 22:11:26 +00:00
static switch_status_t chat_send ( char * proto , char * from , char * to , char * subject , char * body , char * hint ) ;
2006-08-25 23:55:59 +00:00
/* BODY OF THE MODULE */
/*************************************************************************************************************************************************************/
2006-09-28 21:21:44 +00:00
2006-09-29 18:12:31 +00:00
typedef enum {
AUTH_OK ,
AUTH_FORBIDDEN ,
AUTH_STALE ,
} auth_res_t ;
2006-11-14 18:12:17 +00:00
2007-03-19 21:09:53 +00:00
static sofia_profile_t * find_profile ( char * key )
{
static sofia_profile_t * profile ;
switch_mutex_lock ( globals . hash_mutex ) ;
profile = ( sofia_profile_t * ) switch_core_hash_find ( globals . profile_hash , key ) ;
switch_mutex_unlock ( globals . hash_mutex ) ;
return profile ;
}
2007-03-29 22:31:56 +00:00
static void add_profile ( char * key , sofia_profile_t * profile )
2007-03-19 21:09:53 +00:00
{
switch_mutex_lock ( globals . hash_mutex ) ;
2007-03-29 22:31:56 +00:00
switch_core_hash_insert ( globals . profile_hash , key , profile ) ;
2007-03-19 21:09:53 +00:00
switch_mutex_unlock ( globals . hash_mutex ) ;
}
static outbound_reg_t * find_gateway ( char * key )
{
outbound_reg_t * gateway ;
switch_mutex_lock ( globals . hash_mutex ) ;
gateway = ( outbound_reg_t * ) switch_core_hash_find ( globals . gateway_hash , key ) ;
switch_mutex_unlock ( globals . hash_mutex ) ;
return gateway ;
}
2007-03-29 22:31:56 +00:00
static void add_gateway ( char * key , outbound_reg_t * gateway )
2007-03-19 21:09:53 +00:00
{
switch_mutex_lock ( globals . hash_mutex ) ;
switch_core_hash_insert ( globals . gateway_hash , key , gateway ) ;
switch_mutex_unlock ( globals . hash_mutex ) ;
}
2007-02-14 03:24:20 +00:00
static char * get_url_from_contact ( char * buf , uint8_t to_dup )
2006-11-14 18:12:17 +00:00
{
char * url = NULL , * e ;
if ( ( url = strchr ( buf , ' < ' ) ) & & ( e = strchr ( url , ' > ' ) ) ) {
url + + ;
2007-02-14 03:24:20 +00:00
if ( to_dup ) {
2006-11-14 18:12:17 +00:00
url = strdup ( url ) ;
e = strchr ( url , ' > ' ) ;
}
* e = ' \0 ' ;
}
2007-03-29 22:31:56 +00:00
2006-11-14 18:12:17 +00:00
return url ;
}
2007-03-30 00:13:31 +00:00
static auth_res_t parse_auth ( sofia_profile_t * profile , sip_authorization_t const * authorization , const char * regstr , char * np , size_t nplen )
2006-09-29 18:12:31 +00:00
{
2007-02-14 03:24:20 +00:00
int indexnum ;
const char * cur ;
2006-09-29 18:12:31 +00:00
su_md5_t ctx ;
char uridigest [ 2 * SU_MD5_DIGEST_SIZE + 1 ] ;
char bigdigest [ 2 * SU_MD5_DIGEST_SIZE + 1 ] ;
char * nonce , * uri , * qop , * cnonce , * nc , * response , * input = NULL , * input2 = NULL ;
2006-12-13 20:10:00 +00:00
auth_res_t ret = AUTH_FORBIDDEN ;
2006-09-29 18:12:31 +00:00
char * npassword = NULL ;
2006-10-04 23:11:11 +00:00
int cnt = 0 ;
2006-10-05 03:11:09 +00:00
nonce = uri = qop = cnonce = nc = response = NULL ;
2006-10-04 23:11:11 +00:00
if ( authorization - > au_params ) {
2007-03-29 22:31:56 +00:00
for ( indexnum = 0 ; ( cur = authorization - > au_params [ indexnum ] ) ; indexnum + + ) {
char * var , * val , * p , * work ;
2006-10-04 23:11:11 +00:00
var = val = work = NULL ;
if ( ( work = strdup ( cur ) ) ) {
var = work ;
if ( ( val = strchr ( var , ' = ' ) ) ) {
2006-09-29 18:12:31 +00:00
* val + + = ' \0 ' ;
2007-03-29 22:31:56 +00:00
while ( * val = = ' " ' ) {
2006-10-04 23:11:11 +00:00
* val + + = ' \0 ' ;
}
if ( ( p = strchr ( val , ' " ' ) ) ) {
* p = ' \0 ' ;
}
2006-09-29 18:12:31 +00:00
2006-10-04 23:11:11 +00:00
if ( ! strcasecmp ( var , " nonce " ) ) {
nonce = strdup ( val ) ;
cnt + + ;
} else if ( ! strcasecmp ( var , " uri " ) ) {
uri = strdup ( val ) ;
cnt + + ;
} else if ( ! strcasecmp ( var , " qop " ) ) {
qop = strdup ( val ) ;
cnt + + ;
} else if ( ! strcasecmp ( var , " cnonce " ) ) {
cnonce = strdup ( val ) ;
cnt + + ;
} else if ( ! strcasecmp ( var , " response " ) ) {
response = strdup ( val ) ;
cnt + + ;
} else if ( ! strcasecmp ( var , " nc " ) ) {
nc = strdup ( val ) ;
cnt + + ;
}
2006-09-29 18:12:31 +00:00
}
2007-03-29 22:31:56 +00:00
2006-10-04 23:11:11 +00:00
free ( work ) ;
}
2006-09-29 18:12:31 +00:00
}
}
2006-10-04 23:11:11 +00:00
if ( cnt ! = 6 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Authorization header! \n " ) ;
goto end ;
}
2006-09-29 18:12:31 +00:00
if ( switch_strlen_zero ( np ) ) {
2006-09-30 00:00:07 +00:00
if ( ! get_auth_data ( profile - > dbname , nonce , np , nplen , profile - > ireg_mutex ) ) {
2006-09-29 18:12:31 +00:00
ret = AUTH_STALE ;
goto end ;
2007-03-29 22:31:56 +00:00
}
2006-09-29 18:12:31 +00:00
}
npassword = np ;
2006-10-19 16:33:54 +00:00
if ( ( input = switch_mprintf ( " %s:%q " , regstr , uri ) ) ) {
2006-09-29 18:12:31 +00:00
su_md5_init ( & ctx ) ;
su_md5_strupdate ( & ctx , input ) ;
su_md5_hexdigest ( & ctx , uridigest ) ;
su_md5_deinit ( & ctx ) ;
}
2006-10-19 16:33:54 +00:00
if ( ( input2 = switch_mprintf ( " %q:%q:%q:%q:%q:%q " , npassword , nonce , nc , cnonce , qop , uridigest ) ) ) {
2006-09-29 18:12:31 +00:00
memset ( & ctx , 0 , sizeof ( ctx ) ) ;
su_md5_init ( & ctx ) ;
su_md5_strupdate ( & ctx , input2 ) ;
su_md5_hexdigest ( & ctx , bigdigest ) ;
su_md5_deinit ( & ctx ) ;
2006-12-13 20:10:00 +00:00
2006-09-29 18:12:31 +00:00
if ( ! strcasecmp ( bigdigest , response ) ) {
ret = AUTH_OK ;
} else {
ret = AUTH_FORBIDDEN ;
}
}
2007-03-29 22:31:56 +00:00
end :
switch_safe_free ( input ) ;
switch_safe_free ( input2 ) ;
2006-09-29 18:12:31 +00:00
switch_safe_free ( nonce ) ;
switch_safe_free ( uri ) ;
switch_safe_free ( qop ) ;
switch_safe_free ( cnonce ) ;
switch_safe_free ( nc ) ;
switch_safe_free ( response ) ;
return ret ;
}
2007-03-30 00:13:31 +00:00
static void execute_sql ( char * dbname , char * sql , switch_mutex_t * mutex )
2006-09-28 21:21:44 +00:00
{
switch_core_db_t * db ;
if ( mutex ) {
switch_mutex_lock ( mutex ) ;
}
if ( ! ( db = switch_core_db_open_file ( dbname ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB %s \n " , dbname ) ;
goto end ;
}
switch_core_db_persistant_execute ( db , sql , 25 ) ;
switch_core_db_close ( db ) ;
2007-03-29 22:31:56 +00:00
end :
2006-09-28 21:21:44 +00:00
if ( mutex ) {
switch_mutex_unlock ( mutex ) ;
}
}
2006-09-27 03:44:14 +00:00
struct callback_t {
char * val ;
switch_size_t len ;
int matches ;
} ;
2007-03-29 22:31:56 +00:00
static int find_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
2006-09-27 03:44:14 +00:00
struct callback_t * cbt = ( struct callback_t * ) pArg ;
switch_copy_string ( cbt - > val , argv [ 0 ] , cbt - > len ) ;
cbt - > matches + + ;
return 0 ;
}
2007-03-29 22:31:56 +00:00
static int del_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
2006-09-27 03:44:14 +00:00
switch_event_t * s_event ;
2007-03-29 22:31:56 +00:00
if ( argc > = 3 ) {
2006-09-27 03:44:14 +00:00
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_EXPIRE ) = = SWITCH_STATUS_SUCCESS ) {
2006-09-27 20:18:14 +00:00
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " profile-name " , " %s " , argv [ 0 ] ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " user " , " %s " , argv [ 1 ] ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " host " , " %s " , argv [ 2 ] ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " contact " , " %s " , argv [ 3 ] ) ;
2007-03-09 23:51:52 +00:00
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " expires " , " %s " , argv [ 4 ] ) ;
2006-09-27 03:44:14 +00:00
switch_event_fire ( & s_event ) ;
}
}
return 0 ;
}
2007-03-30 00:13:31 +00:00
static void check_expire ( switch_core_db_t * db , sofia_profile_t * profile , time_t now )
2006-09-27 03:44:14 +00:00
{
char sql [ 1024 ] ;
char * errmsg ;
2006-09-27 04:34:19 +00:00
2006-12-28 01:08:06 +00:00
if ( ! db ) {
2006-09-27 04:34:19 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB %s \n " , profile - > dbname ) ;
return ;
}
2006-09-27 03:44:14 +00:00
2006-09-30 00:00:07 +00:00
switch_mutex_lock ( profile - > ireg_mutex ) ;
2007-03-30 00:13:31 +00:00
snprintf ( sql , sizeof ( sql ) , " select '%s',* from sip_registrations where expires > 0 and expires < %ld " , profile - > name , ( long ) now ) ;
2006-09-27 04:34:19 +00:00
switch_core_db_exec ( db , sql , del_callback , NULL , & errmsg ) ;
2006-09-27 03:44:14 +00:00
if ( errmsg ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " SQL ERR [%s][%s] \n " , sql , errmsg ) ;
2006-10-19 16:33:54 +00:00
switch_safe_free ( errmsg ) ;
2006-09-27 03:44:14 +00:00
errmsg = NULL ;
}
2007-03-29 22:31:56 +00:00
2006-09-27 03:44:14 +00:00
snprintf ( sql , sizeof ( sql ) , " delete from sip_registrations where expires > 0 and expires < %ld " , ( long ) now ) ;
2006-10-15 05:10:34 +00:00
switch_core_db_persistant_execute ( db , sql , 1000 ) ;
2006-09-28 21:21:44 +00:00
snprintf ( sql , sizeof ( sql ) , " delete from sip_authentication where expires > 0 and expires < %ld " , ( long ) now ) ;
2006-10-15 05:10:34 +00:00
switch_core_db_persistant_execute ( db , sql , 1000 ) ;
snprintf ( sql , sizeof ( sql ) , " delete from sip_subscriptions where expires > 0 and expires < %ld " , ( long ) now ) ;
switch_core_db_persistant_execute ( db , sql , 1000 ) ;
2006-09-30 00:00:07 +00:00
switch_mutex_unlock ( profile - > ireg_mutex ) ;
2006-09-27 04:34:19 +00:00
2006-09-27 03:44:14 +00:00
}
2007-03-29 22:31:56 +00:00
static char * find_reg_url ( sofia_profile_t * profile , const char * user , const char * host , char * val , switch_size_t len )
2006-09-27 03:44:14 +00:00
{
char * errmsg ;
2007-03-29 22:31:56 +00:00
struct callback_t cbt = { 0 } ;
2006-09-27 04:34:19 +00:00
switch_core_db_t * db ;
2006-09-27 03:44:14 +00:00
2007-03-05 06:04:37 +00:00
if ( ! user ) {
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Called with null user! \n " ) ;
return NULL ;
2007-03-05 06:04:37 +00:00
}
2006-09-27 04:34:19 +00:00
if ( ! ( db = switch_core_db_open_file ( profile - > dbname ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB %s \n " , profile - > dbname ) ;
return NULL ;
}
2006-09-27 03:44:14 +00:00
cbt . val = val ;
cbt . len = len ;
2006-09-30 00:00:07 +00:00
switch_mutex_lock ( profile - > ireg_mutex ) ;
2006-09-27 03:44:14 +00:00
if ( host ) {
2007-03-29 22:31:56 +00:00
snprintf ( val , len , " select contact from sip_registrations where user='%s' and host='%s' " , user , host ) ;
2006-09-27 03:44:14 +00:00
} else {
2007-03-29 22:31:56 +00:00
snprintf ( val , len , " select contact from sip_registrations where user='%s' " , user ) ;
2006-09-27 03:44:14 +00:00
}
2006-09-27 04:34:19 +00:00
switch_core_db_exec ( db , val , find_callback , & cbt , & errmsg ) ;
2006-09-27 03:44:14 +00:00
if ( errmsg ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " SQL ERR [%s][%s] \n " , val , errmsg ) ;
2006-10-19 16:33:54 +00:00
switch_safe_free ( errmsg ) ;
2006-09-27 03:44:14 +00:00
errmsg = NULL ;
}
2006-09-30 00:00:07 +00:00
switch_mutex_unlock ( profile - > ireg_mutex ) ;
2006-09-27 04:34:19 +00:00
switch_core_db_close ( db ) ;
2007-03-29 22:31:56 +00:00
if ( cbt . matches ) {
return val ;
} else {
return NULL ;
}
2006-09-27 03:44:14 +00:00
}
2007-03-29 22:31:56 +00:00
static void set_local_sdp ( private_object_t * tech_pvt , char * ip , uint32_t port , char * sr , int force )
2006-08-25 23:55:59 +00:00
{
2007-02-20 17:50:50 +00:00
char buf [ 2048 ] ;
2006-08-25 23:55:59 +00:00
switch_time_t now = switch_time_now ( ) ;
2007-03-29 22:31:56 +00:00
int ptime = 0 ;
2007-03-08 02:31:34 +00:00
int rate = 0 ;
2006-08-25 23:55:59 +00:00
2006-10-31 21:38:06 +00:00
if ( ! force & & ! ip & & ! sr & & switch_test_flag ( tech_pvt , TFLAG_NOMEDIA ) ) {
2006-10-06 22:39:49 +00:00
return ;
}
2006-10-31 21:38:06 +00:00
if ( ! ip ) {
if ( ! ( ip = tech_pvt - > adv_sdp_audio_ip ) ) {
ip = tech_pvt - > proxy_sdp_audio_ip ;
}
}
if ( ! port ) {
if ( ! ( port = tech_pvt - > adv_sdp_audio_port ) ) {
port = tech_pvt - > proxy_sdp_audio_port ;
}
}
if ( ! sr ) {
sr = " sendrecv " ;
}
2007-03-29 22:31:56 +00:00
snprintf ( buf , sizeof ( buf ) ,
2006-08-25 23:55:59 +00:00
" v=0 \n "
2007-03-29 22:31:56 +00:00
" o=FreeSWITCH %d% " SWITCH_TIME_T_FMT " %d% " SWITCH_TIME_T_FMT " IN IP4 %s \n "
2007-03-30 00:13:31 +00:00
" s=FreeSWITCH \n " " c=IN IP4 %s \n " " t=0 0 \n " " a=%s \n " " m=audio %d RTP/AVP " , port , now , port , now , ip , ip , sr , port ) ;
2006-08-25 23:55:59 +00:00
if ( tech_pvt - > rm_encoding ) {
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " %d " , tech_pvt - > pt ) ;
} else if ( tech_pvt - > num_codecs ) {
int i ;
for ( i = 0 ; i < tech_pvt - > num_codecs ; i + + ) {
const switch_codec_implementation_t * imp = tech_pvt - > codecs [ i ] ;
2007-02-03 19:47:21 +00:00
2006-08-25 23:55:59 +00:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " %d " , imp - > ianacode ) ;
2007-03-29 22:31:56 +00:00
if ( ! ptime ) {
ptime = imp - > microseconds_per_frame / 1000 ;
}
2006-08-25 23:55:59 +00:00
}
}
2006-10-09 02:24:43 +00:00
if ( tech_pvt - > te > 95 ) {
2006-08-25 23:55:59 +00:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " %d " , tech_pvt - > te ) ;
}
2007-03-07 18:34:22 +00:00
if ( tech_pvt - > cng_pt ) {
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " %d " , tech_pvt - > cng_pt ) ;
}
2006-08-25 23:55:59 +00:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " \n " ) ;
if ( tech_pvt - > rm_encoding ) {
2007-03-07 20:23:14 +00:00
rate = tech_pvt - > rm_rate ;
2007-03-30 00:13:31 +00:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " a=rtpmap:%d %s/%ld \n " , tech_pvt - > pt , tech_pvt - > rm_encoding , tech_pvt - > rm_rate ) ;
2006-10-09 02:24:43 +00:00
if ( tech_pvt - > fmtp_out ) {
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " a=fmtp:%d %s \n " , tech_pvt - > pt , tech_pvt - > fmtp_out ) ;
}
2007-03-29 22:31:56 +00:00
if ( tech_pvt - > read_codec . implementation & & ! ptime ) {
ptime = tech_pvt - > read_codec . implementation - > microseconds_per_frame / 1000 ;
2006-10-09 02:24:43 +00:00
}
2006-08-25 23:55:59 +00:00
} else if ( tech_pvt - > num_codecs ) {
int i ;
for ( i = 0 ; i < tech_pvt - > num_codecs ; i + + ) {
const switch_codec_implementation_t * imp = tech_pvt - > codecs [ i ] ;
2007-03-20 23:11:20 +00:00
uint32_t rfc_3551_sucks = imp - > samples_per_second ;
2007-03-29 22:31:56 +00:00
2007-03-07 20:23:14 +00:00
if ( ! rate ) {
rate = imp - > samples_per_second ;
}
2007-03-29 22:31:56 +00:00
if ( ptime & & ptime ! = imp - > microseconds_per_frame / 1000 ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " ptime %u != advertised ptime %u \n " , imp - > microseconds_per_frame / 1000 , ptime ) ;
2007-03-29 22:31:56 +00:00
}
2007-03-20 23:11:20 +00:00
if ( rfc_3551_sucks & & imp - > ianacode = = 9 ) {
rfc_3551_sucks = 8000 ;
}
2007-03-30 00:13:31 +00:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " a=rtpmap:%d %s/%d \n " , imp - > ianacode , imp - > iananame , rfc_3551_sucks ) ;
2006-10-09 02:24:43 +00:00
if ( imp - > fmtp ) {
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " a=fmtp:%d %s \n " , imp - > ianacode , imp - > fmtp ) ;
}
2006-08-25 23:55:59 +00:00
}
}
2007-03-29 22:31:56 +00:00
2006-10-09 02:24:43 +00:00
if ( tech_pvt - > te > 95 ) {
2007-03-30 00:13:31 +00:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " a=rtpmap:%d telephone-event/8000 \n a=fmtp:%d 0-16 \n " , tech_pvt - > te , tech_pvt - > te ) ;
2006-08-25 23:55:59 +00:00
}
2007-03-07 23:24:09 +00:00
if ( tech_pvt - > cng_pt ) {
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " a=rtpmap:%d CN/%d \n " , tech_pvt - > cng_pt , rate ) ;
2007-03-08 02:52:31 +00:00
if ( ! tech_pvt - > rm_encoding ) {
tech_pvt - > cng_pt = 0 ;
}
2007-03-07 23:24:09 +00:00
}
2007-03-29 22:31:56 +00:00
if ( ptime ) {
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " a=ptime:%d \n " , ptime ) ;
}
2007-02-03 19:47:21 +00:00
2006-08-25 23:55:59 +00:00
tech_pvt - > local_sdp_str = switch_core_session_strdup ( tech_pvt - > session , buf ) ;
}
2007-03-29 22:31:56 +00:00
static void tech_set_codecs ( private_object_t * tech_pvt )
2006-08-25 23:55:59 +00:00
{
2007-03-29 22:31:56 +00:00
switch_channel_t * channel ;
char * abs , * codec_string = NULL ;
char * ocodec = NULL ;
2006-10-06 22:39:49 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_NOMEDIA ) ) {
return ;
}
2006-08-25 23:55:59 +00:00
if ( tech_pvt - > num_codecs ) {
return ;
}
2007-03-29 22:31:56 +00:00
assert ( tech_pvt - > session ! = NULL ) ;
2006-12-01 21:24:54 +00:00
2007-03-29 22:31:56 +00:00
channel = switch_core_session_get_channel ( tech_pvt - > session ) ;
assert ( channel ! = NULL ) ;
2006-12-01 21:24:54 +00:00
2007-01-28 17:37:51 +00:00
2007-03-29 22:31:56 +00:00
if ( ( abs = switch_channel_get_variable ( channel , " absolute_codec_string " ) ) ) {
codec_string = abs ;
} else {
if ( ! ( codec_string = switch_channel_get_variable ( channel , " codec_string " ) ) ) {
2007-02-14 22:14:32 +00:00
if ( tech_pvt - > profile - > codec_string ) {
2007-02-16 19:43:00 +00:00
codec_string = tech_pvt - > profile - > codec_string ;
2007-02-14 22:14:32 +00:00
}
2007-03-29 22:31:56 +00:00
}
if ( ( ocodec = switch_channel_get_variable ( channel , SWITCH_ORIGINATOR_CODEC_VARIABLE ) ) ) {
if ( ! codec_string | | ( tech_pvt - > profile - > pflags & PFLAG_DISABLE_TRANSCODING ) ) {
codec_string = ocodec ;
} else {
2007-03-19 21:09:53 +00:00
if ( ! ( codec_string = switch_core_session_sprintf ( tech_pvt - > session , " %s,%s " , ocodec , codec_string ) ) ) {
codec_string = ocodec ;
}
2007-03-29 22:31:56 +00:00
}
}
}
2007-01-28 17:37:51 +00:00
2006-12-01 21:24:54 +00:00
if ( codec_string ) {
2007-02-16 19:43:00 +00:00
char * tmp_codec_string ;
2007-03-19 21:09:53 +00:00
if ( ( tmp_codec_string = switch_core_session_strdup ( tech_pvt - > session , codec_string ) ) ) {
2007-03-30 00:13:31 +00:00
tech_pvt - > codec_order_last = switch_separate_string ( tmp_codec_string , ' , ' , tech_pvt - > codec_order , SWITCH_MAX_CODECS ) ;
2007-03-29 22:31:56 +00:00
tech_pvt - > num_codecs =
2007-03-30 00:13:31 +00:00
switch_loadable_module_get_codecs_sorted ( tech_pvt - > codecs , SWITCH_MAX_CODECS , tech_pvt - > codec_order , tech_pvt - > codec_order_last ) ;
2007-02-16 19:43:00 +00:00
}
2006-08-25 23:55:59 +00:00
} else {
2007-03-29 22:31:56 +00:00
tech_pvt - > num_codecs =
switch_loadable_module_get_codecs ( switch_core_session_get_pool ( tech_pvt - > session ) , tech_pvt - > codecs ,
sizeof ( tech_pvt - > codecs ) / sizeof ( tech_pvt - > codecs [ 0 ] ) ) ;
2006-08-25 23:55:59 +00:00
}
2007-01-28 17:37:51 +00:00
2006-08-25 23:55:59 +00:00
}
2007-01-26 21:12:19 +00:00
2007-03-30 00:13:31 +00:00
static void attach_private ( switch_core_session_t * session , sofia_profile_t * profile , private_object_t * tech_pvt , const char * channame )
2006-08-25 23:55:59 +00:00
{
switch_channel_t * channel ;
char name [ 256 ] ;
assert ( session ! = NULL ) ;
assert ( profile ! = NULL ) ;
assert ( tech_pvt ! = NULL ) ;
switch_core_session_add_stream ( session , NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
2007-03-29 22:31:56 +00:00
2007-03-07 22:30:29 +00:00
//switch_channel_set_flag(channel, CF_ACCEPT_CNG);
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
switch_mutex_init ( & tech_pvt - > flag_mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( session ) ) ;
switch_mutex_lock ( tech_pvt - > flag_mutex ) ;
tech_pvt - > flags = profile - > flags ;
switch_mutex_unlock ( tech_pvt - > flag_mutex ) ;
tech_pvt - > profile = profile ;
2007-02-21 21:46:32 +00:00
if ( tech_pvt - > bte ) {
tech_pvt - > te = tech_pvt - > bte ;
2007-03-07 20:06:15 +00:00
} else if ( ! tech_pvt - > te ) {
2007-02-21 21:46:32 +00:00
tech_pvt - > te = profile - > te ;
}
2007-03-07 18:34:22 +00:00
if ( tech_pvt - > bcng_pt ) {
tech_pvt - > cng_pt = tech_pvt - > bcng_pt ;
2007-03-07 20:06:15 +00:00
} else if ( ! tech_pvt - > cng_pt ) {
2007-03-07 18:34:22 +00:00
tech_pvt - > cng_pt = profile - > cng_pt ;
}
2006-08-25 23:55:59 +00:00
tech_pvt - > session = session ;
2006-08-28 16:40:05 +00:00
tech_pvt - > home = su_home_new ( sizeof ( * tech_pvt - > home ) ) ;
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
switch_core_session_set_private ( session , tech_pvt ) ;
2007-01-28 17:37:51 +00:00
2006-08-25 23:55:59 +00:00
snprintf ( name , sizeof ( name ) , " sofia/%s/%s " , profile - > name , channame ) ;
2007-03-29 22:31:56 +00:00
switch_channel_set_name ( channel , name ) ;
2007-01-28 17:37:51 +00:00
//tech_set_codecs(tech_pvt);
2007-01-26 21:12:19 +00:00
2006-08-25 23:55:59 +00:00
}
2006-08-26 21:13:56 +00:00
static void terminate_session ( switch_core_session_t * * session , switch_call_cause_t cause , int line )
2006-08-25 23:55:59 +00:00
{
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Term called from line: %d \n " , line ) ;
if ( * session ) {
switch_channel_t * channel = switch_core_session_get_channel ( * session ) ;
struct private_object * tech_pvt = NULL ;
unsigned running = switch_core_session_running ( * session ) ;
tech_pvt = switch_core_session_get_private ( * session ) ;
if ( running ) {
switch_channel_hangup ( channel , cause ) ;
} else {
if ( tech_pvt ) {
sofia_on_hangup ( * session ) ;
}
if ( session & & * session ) {
switch_core_session_destroy ( session ) ;
}
}
}
2006-08-25 23:55:59 +00:00
}
2006-10-31 21:38:06 +00:00
2007-03-08 20:05:09 +00:00
2007-03-30 00:13:31 +00:00
static switch_status_t sofia_ext_address_lookup ( char * * ip , switch_port_t * port , char * sourceip , switch_memory_pool_t * pool )
2007-03-08 20:05:09 +00:00
{
char * error ;
2007-03-29 22:31:56 +00:00
2007-03-08 20:05:09 +00:00
if ( ! sourceip ) {
return SWITCH_STATUS_FALSE ;
}
if ( ! strncasecmp ( sourceip , " stun: " , 5 ) ) {
char * stun_ip = sourceip + 5 ;
if ( ! stun_ip ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Stun Failed! NO STUN SERVER \n " ) ;
return SWITCH_STATUS_FALSE ;
}
2007-03-29 22:31:56 +00:00
if ( switch_stun_lookup ( ip , port , stun_ip , SWITCH_STUN_DEFAULT_PORT , & error , pool ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Stun Failed! %s:%d [%s] \n " , stun_ip , SWITCH_STUN_DEFAULT_PORT , error ) ;
2007-03-08 20:05:09 +00:00
return SWITCH_STATUS_FALSE ;
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Stun Success [%s]:[%d] \n " , * ip , * port ) ;
} else {
* ip = sourceip ;
}
return SWITCH_STATUS_SUCCESS ;
}
2007-03-29 22:31:56 +00:00
static switch_status_t tech_choose_port ( private_object_t * tech_pvt )
2006-08-25 23:55:59 +00:00
{
char * ip = tech_pvt - > profile - > rtpip ;
2006-10-31 21:38:06 +00:00
switch_channel_t * channel ;
2006-08-25 23:55:59 +00:00
switch_port_t sdp_port ;
2006-10-31 21:38:06 +00:00
char tmp [ 50 ] ;
2006-10-06 22:39:49 +00:00
2006-10-31 21:38:06 +00:00
channel = switch_core_session_get_channel ( tech_pvt - > session ) ;
2007-03-29 22:31:56 +00:00
2006-10-06 22:39:49 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_NOMEDIA ) | | tech_pvt - > adv_sdp_audio_port ) {
2006-08-25 23:55:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
tech_pvt - > local_sdp_audio_ip = ip ;
tech_pvt - > local_sdp_audio_port = switch_rtp_request_port ( ) ;
sdp_port = tech_pvt - > local_sdp_audio_port ;
if ( tech_pvt - > profile - > extrtpip ) {
2007-03-30 00:13:31 +00:00
if ( sofia_ext_address_lookup ( & ip , & sdp_port , tech_pvt - > profile - > extrtpip , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:31:56 +00:00
terminate_session ( & tech_pvt - > session , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER , __LINE__ ) ;
return SWITCH_STATUS_FALSE ;
2006-08-25 23:55:59 +00:00
}
}
tech_pvt - > adv_sdp_audio_ip = switch_core_session_strdup ( tech_pvt - > session , ip ) ;
tech_pvt - > adv_sdp_audio_port = sdp_port ;
2006-10-31 21:38:06 +00:00
snprintf ( tmp , sizeof ( tmp ) , " %d " , sdp_port ) ;
switch_channel_set_variable ( channel , SWITCH_LOCAL_MEDIA_IP_VARIABLE , tech_pvt - > adv_sdp_audio_ip ) ;
switch_channel_set_variable ( channel , SWITCH_LOCAL_MEDIA_PORT_VARIABLE , tmp ) ;
2007-03-29 22:31:56 +00:00
2006-10-31 21:38:06 +00:00
2006-08-25 23:55:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-03-01 16:11:08 +00:00
static switch_status_t do_invite ( switch_core_session_t * session )
2006-08-25 23:55:59 +00:00
{
2006-10-19 16:10:24 +00:00
char rpid [ 1024 ] = { 0 } ;
2006-10-19 16:42:41 +00:00
char alert_info [ 1024 ] = { 0 } ;
2007-02-06 18:11:25 +00:00
char max_forwards [ 8 ] = { 0 } ;
2006-10-19 16:42:41 +00:00
char * alertbuf ;
2007-02-06 18:11:25 +00:00
char * forwardbuf ;
int forwardval ;
2006-08-25 23:55:59 +00:00
private_object_t * tech_pvt ;
2007-03-29 22:31:56 +00:00
switch_channel_t * channel = NULL ;
2006-10-05 00:38:45 +00:00
switch_caller_profile_t * caller_profile ;
2006-10-20 22:11:26 +00:00
char * cid_name , * cid_num ;
2006-10-18 22:57:35 +00:00
char * e_dest = NULL ;
2007-02-14 19:15:20 +00:00
const char * holdstr = " " ;
2007-03-29 22:31:56 +00:00
switch_stream_handle_t stream = { 0 } ;
2007-02-13 01:22:17 +00:00
switch_hash_index_t * hi ;
void * vval ;
2007-02-13 21:52:33 +00:00
char * extra_headers = NULL ;
2007-02-13 01:22:17 +00:00
const void * vvar ;
2007-03-01 16:11:08 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2007-03-19 21:09:53 +00:00
char * rep ;
2006-08-25 23:55:59 +00:00
2007-03-29 22:31:56 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2006-08-25 23:55:59 +00:00
2007-03-19 21:09:53 +00:00
rep = switch_channel_get_variable ( channel , SOFIA_REPLACES_HEADER ) ;
2007-03-29 22:31:56 +00:00
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2006-08-25 23:55:59 +00:00
2006-10-05 04:25:32 +00:00
caller_profile = switch_channel_get_caller_profile ( channel ) ;
2006-10-18 22:57:35 +00:00
cid_name = ( char * ) caller_profile - > caller_id_name ;
cid_num = ( char * ) caller_profile - > caller_id_number ;
2007-03-29 22:31:56 +00:00
tech_set_codecs ( tech_pvt ) ;
2007-01-28 17:37:51 +00:00
2007-03-19 21:09:53 +00:00
if ( ! tech_pvt - > from_str ) {
2007-03-29 22:31:56 +00:00
tech_pvt - > from_str = switch_core_session_sprintf ( tech_pvt - > session , " \" %s \" <sip:%s@%s> " ,
2007-03-19 21:09:53 +00:00
cid_name ,
2007-03-30 00:13:31 +00:00
cid_num , tech_pvt - > profile - > extsipip ? tech_pvt - > profile - > extsipip : tech_pvt - > profile - > sipip ) ;
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
}
2006-10-05 04:06:07 +00:00
2007-03-19 21:09:53 +00:00
if ( ! tech_pvt - > from_str ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Memory Error! \n " ) ;
return SWITCH_STATUS_FALSE ;
}
2006-10-19 16:42:41 +00:00
2006-10-18 22:57:35 +00:00
2007-02-06 18:11:25 +00:00
2007-03-19 21:09:53 +00:00
if ( ( alertbuf = switch_channel_get_variable ( channel , " alert_info " ) ) ) {
snprintf ( alert_info , sizeof ( alert_info ) - 1 , " Alert-Info: %s " , alertbuf ) ;
}
if ( ( forwardbuf = switch_channel_get_variable ( channel , SWITCH_MAX_FORWARDS_VARIABLE ) ) ) {
forwardval = atoi ( forwardbuf ) - 1 ;
snprintf ( max_forwards , sizeof ( max_forwards ) - 1 , " %d " , forwardval ) ;
}
if ( tech_choose_port ( tech_pvt ) ! = SWITCH_STATUS_SUCCESS ) {
return status ;
}
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
set_local_sdp ( tech_pvt , NULL , 0 , NULL , 0 ) ;
2006-10-06 22:39:49 +00:00
2007-03-19 21:09:53 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_READY ) ;
2006-10-05 04:06:07 +00:00
2007-03-19 21:09:53 +00:00
// forge a RPID for now KHR -- Should wrap this in an if statement so it can be turned on and off
if ( switch_test_flag ( caller_profile , SWITCH_CPF_SCREEN ) ) {
const char * priv = " off " ;
const char * screen = " no " ;
if ( switch_test_flag ( caller_profile , SWITCH_CPF_HIDE_NAME ) ) {
priv = " name " ;
if ( switch_test_flag ( caller_profile , SWITCH_CPF_HIDE_NUMBER ) ) {
2006-10-16 04:39:00 +00:00
priv = " yes " ;
}
2007-03-19 21:09:53 +00:00
} else if ( switch_test_flag ( caller_profile , SWITCH_CPF_HIDE_NUMBER ) ) {
priv = " yes " ;
}
if ( switch_test_flag ( caller_profile , SWITCH_CPF_SCREEN ) ) {
screen = " yes " ;
2006-10-16 04:39:00 +00:00
}
2007-03-30 00:13:31 +00:00
snprintf ( rpid , sizeof ( rpid ) - 1 , " Remote-Party-ID: %s;party=calling;screen=%s;privacy=%s " , tech_pvt - > from_str , screen , priv ) ;
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
}
2006-10-06 22:39:49 +00:00
2007-03-19 21:09:53 +00:00
if ( ! tech_pvt - > nh ) {
2007-03-29 22:31:56 +00:00
char * url = get_url_from_contact ( tech_pvt - > dest , 1 ) ;
2007-03-19 21:09:53 +00:00
tech_pvt - > nh = nua_handle ( tech_pvt - > profile - > nua , NULL ,
NUTAG_URL ( url ) ,
2007-03-30 00:13:31 +00:00
SIPTAG_TO_STR ( tech_pvt - > dest_to ) , SIPTAG_FROM_STR ( tech_pvt - > from_str ) , SIPTAG_CONTACT_STR ( tech_pvt - > profile - > url ) , TAG_END ( ) ) ;
2007-03-19 21:09:53 +00:00
switch_safe_free ( url ) ;
2006-10-06 22:39:49 +00:00
2007-03-19 21:09:53 +00:00
if ( ! ( tech_pvt - > sofia_private = malloc ( sizeof ( * tech_pvt - > sofia_private ) ) ) ) {
abort ( ) ;
2006-10-06 22:39:49 +00:00
}
2007-03-19 21:09:53 +00:00
memset ( tech_pvt - > sofia_private , 0 , sizeof ( * tech_pvt - > sofia_private ) ) ;
2007-03-30 00:13:31 +00:00
switch_copy_string ( tech_pvt - > sofia_private - > uuid , switch_core_session_get_uuid ( session ) , sizeof ( tech_pvt - > sofia_private - > uuid ) ) ;
2007-03-19 21:09:53 +00:00
nua_handle_bind ( tech_pvt - > nh , tech_pvt - > sofia_private ) ;
2006-10-06 22:39:49 +00:00
2007-03-19 21:09:53 +00:00
}
2006-10-18 22:57:35 +00:00
2007-03-19 21:09:53 +00:00
if ( tech_pvt - > e_dest & & ( e_dest = strdup ( tech_pvt - > e_dest ) ) ) {
char * user = e_dest , * host = NULL ;
char hash_key [ 256 ] = " " ;
2006-10-18 22:57:35 +00:00
2007-03-19 21:09:53 +00:00
if ( ( host = strchr ( user , ' @ ' ) ) ) {
* host + + = ' \0 ' ;
2006-10-18 22:57:35 +00:00
}
2007-03-19 21:09:53 +00:00
snprintf ( hash_key , sizeof ( hash_key ) , " %s%s%s " , user , host , cid_num ) ;
2006-10-18 22:57:35 +00:00
2007-03-19 21:09:53 +00:00
tech_pvt - > chat_from = tech_pvt - > from_str ;
tech_pvt - > chat_to = tech_pvt - > dest ;
tech_pvt - > hash_key = switch_core_session_strdup ( tech_pvt - > session , hash_key ) ;
switch_core_hash_insert ( tech_pvt - > profile - > chat_hash , tech_pvt - > hash_key , tech_pvt ) ;
2007-03-29 22:31:56 +00:00
free ( e_dest ) ;
2007-03-19 21:09:53 +00:00
}
2007-02-06 18:11:25 +00:00
2007-03-19 21:09:53 +00:00
holdstr = switch_test_flag ( tech_pvt , TFLAG_SIP_HOLD ) ? " * " : " " ;
2007-02-13 01:22:17 +00:00
2007-03-19 21:09:53 +00:00
SWITCH_STANDARD_STREAM ( stream ) ;
2007-03-30 00:13:31 +00:00
for ( hi = switch_channel_variable_first ( channel , switch_core_session_get_pool ( tech_pvt - > session ) ) ; hi ; hi = switch_hash_next ( hi ) ) {
2007-03-19 21:09:53 +00:00
switch_hash_this ( hi , & vvar , NULL , & vval ) ;
if ( vvar & & vval ) {
const char * name = vvar ;
char * value = ( char * ) vval ;
if ( ! strncasecmp ( name , SOFIA_SIP_HEADER_PREFIX , strlen ( SOFIA_SIP_HEADER_PREFIX ) ) ) {
const char * hname = name + strlen ( SOFIA_SIP_HEADER_PREFIX ) ;
stream . write_function ( & stream , " %s: %s \r \n " , hname , value ) ;
2007-02-13 01:22:17 +00:00
}
}
2007-03-19 21:09:53 +00:00
}
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( stream . data ) {
extra_headers = stream . data ;
}
nua_invite ( tech_pvt - > nh ,
TAG_IF ( ! switch_strlen_zero ( rpid ) , SIPTAG_HEADER_STR ( rpid ) ) ,
TAG_IF ( ! switch_strlen_zero ( alert_info ) , SIPTAG_HEADER_STR ( alert_info ) ) ,
TAG_IF ( ! switch_strlen_zero ( extra_headers ) , SIPTAG_HEADER_STR ( extra_headers ) ) ,
2007-03-29 22:31:56 +00:00
TAG_IF ( ! switch_strlen_zero ( max_forwards ) , SIPTAG_MAX_FORWARDS_STR ( max_forwards ) ) ,
2007-03-19 21:09:53 +00:00
//SIPTAG_CONTACT_STR(tech_pvt->profile->url),
SOATAG_USER_SDP_STR ( tech_pvt - > local_sdp_str ) ,
SOATAG_RTP_SORT ( SOA_RTP_SORT_REMOTE ) ,
2007-03-30 00:13:31 +00:00
SOATAG_RTP_SELECT ( SOA_RTP_SELECT_ALL ) , TAG_IF ( rep , SIPTAG_REPLACES_STR ( rep ) ) , SOATAG_HOLD ( holdstr ) , TAG_END ( ) ) ;
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
switch_safe_free ( stream . data ) ;
2007-03-01 16:11:08 +00:00
2007-03-19 21:09:53 +00:00
return SWITCH_STATUS_SUCCESS ;
2007-03-29 22:31:56 +00:00
2006-10-06 22:39:49 +00:00
}
static void do_xfer_invite ( switch_core_session_t * session )
{
2006-10-16 04:39:00 +00:00
char rpid [ 1024 ] ;
2006-10-06 22:39:49 +00:00
private_object_t * tech_pvt ;
2007-03-29 22:31:56 +00:00
switch_channel_t * channel = NULL ;
2006-10-06 22:39:49 +00:00
switch_caller_profile_t * caller_profile ;
2007-03-29 22:31:56 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2006-10-06 22:39:49 +00:00
2007-03-29 22:31:56 +00:00
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2006-10-06 22:39:49 +00:00
caller_profile = switch_channel_get_caller_profile ( channel ) ;
2007-03-29 22:31:56 +00:00
if ( ( tech_pvt - > from_str = switch_core_session_sprintf ( session , " \" %s \" <sip:%s@%s> " ,
( char * ) caller_profile - > caller_id_name ,
( char * ) caller_profile - > caller_id_number ,
2007-03-30 00:13:31 +00:00
tech_pvt - > profile - > extsipip ? tech_pvt - > profile - > extsipip : tech_pvt - > profile - > sipip ) ) ) {
2006-10-06 22:39:49 +00:00
char * rep = switch_channel_get_variable ( channel , SOFIA_REPLACES_HEADER ) ;
tech_pvt - > nh2 = nua_handle ( tech_pvt - > profile - > nua , NULL ,
2007-03-30 00:13:31 +00:00
SIPTAG_TO_STR ( tech_pvt - > dest ) , SIPTAG_FROM_STR ( tech_pvt - > from_str ) , SIPTAG_CONTACT_STR ( tech_pvt - > profile - > url ) , TAG_END ( ) ) ;
2007-03-29 22:31:56 +00:00
2006-12-28 19:38:35 +00:00
nua_handle_bind ( tech_pvt - > nh2 , tech_pvt - > sofia_private ) ;
2006-10-06 22:39:49 +00:00
nua_invite ( tech_pvt - > nh2 ,
2006-10-16 04:39:00 +00:00
TAG_IF ( rpid , SIPTAG_HEADER_STR ( rpid ) ) ,
2006-10-31 21:38:06 +00:00
SIPTAG_CONTACT_STR ( tech_pvt - > profile - > url ) ,
2006-10-05 00:38:45 +00:00
SOATAG_USER_SDP_STR ( tech_pvt - > local_sdp_str ) ,
2007-03-30 00:13:31 +00:00
SOATAG_RTP_SORT ( SOA_RTP_SORT_REMOTE ) , SOATAG_RTP_SELECT ( SOA_RTP_SELECT_ALL ) , TAG_IF ( rep , SIPTAG_REPLACES_STR ( rep ) ) , TAG_END ( ) ) ;
2006-10-05 00:38:45 +00:00
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Memory Error! \n " ) ;
}
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
}
2007-03-29 22:31:56 +00:00
static void tech_absorb_sdp ( private_object_t * tech_pvt )
2006-10-31 21:38:06 +00:00
{
switch_channel_t * channel ;
char * sdp_str ;
channel = switch_core_session_get_channel ( tech_pvt - > session ) ;
assert ( channel ! = NULL ) ;
2007-03-29 15:21:42 +00:00
2006-10-31 21:38:06 +00:00
if ( ( sdp_str = switch_channel_get_variable ( channel , SWITCH_B_SDP_VARIABLE ) ) ) {
sdp_parser_t * parser ;
sdp_session_t * sdp ;
sdp_media_t * m ;
2007-02-25 21:37:02 +00:00
sdp_connection_t * connection ;
2006-10-31 21:38:06 +00:00
2007-03-29 22:31:56 +00:00
if ( ( parser = sdp_parse ( tech_pvt - > home , sdp_str , ( int ) strlen ( sdp_str ) , 0 ) ) ) {
2006-10-31 21:38:06 +00:00
if ( ( sdp = sdp_session ( parser ) ) ) {
2007-03-29 22:31:56 +00:00
for ( m = sdp - > sdp_media ; m ; m = m - > m_next ) {
2007-02-25 21:37:02 +00:00
if ( m - > m_type ! = sdp_media_audio ) {
continue ;
}
connection = sdp - > sdp_connection ;
if ( m - > m_connections ) {
connection = m - > m_connections ;
}
if ( connection ) {
2007-03-30 00:13:31 +00:00
tech_pvt - > proxy_sdp_audio_ip = switch_core_session_strdup ( tech_pvt - > session , connection - > c_address ) ;
2007-02-25 21:37:02 +00:00
}
2007-03-29 22:31:56 +00:00
tech_pvt - > proxy_sdp_audio_port = ( switch_port_t ) m - > m_port ;
2006-10-31 21:46:42 +00:00
if ( tech_pvt - > proxy_sdp_audio_ip & & tech_pvt - > proxy_sdp_audio_port ) {
break ;
}
2006-10-31 21:38:06 +00:00
}
}
sdp_parser_free ( parser ) ;
2007-03-29 22:31:56 +00:00
}
2006-10-31 21:38:06 +00:00
tech_pvt - > local_sdp_str = switch_core_session_strdup ( tech_pvt - > session , sdp_str ) ;
}
}
2006-08-25 23:55:59 +00:00
/*
2006-08-26 21:13:56 +00:00
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 .
2006-08-25 23:55:59 +00:00
*/
static switch_status_t sofia_on_init ( switch_core_session_t * session )
{
private_object_t * tech_pvt ;
switch_channel_t * channel = NULL ;
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
tech_pvt - > read_frame . buflen = SWITCH_RTP_MAX_BUF_LEN ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " SOFIA INIT \n " ) ;
2006-10-06 22:39:49 +00:00
if ( switch_channel_test_flag ( channel , CF_NOMEDIA ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_NOMEDIA ) ;
2006-10-31 21:38:06 +00:00
tech_absorb_sdp ( tech_pvt ) ;
2006-10-06 22:39:49 +00:00
}
2006-08-25 23:55:59 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_OUTBOUND ) ) {
2007-03-01 16:11:08 +00:00
if ( do_invite ( session ) ! = SWITCH_STATUS_SUCCESS ) {
return SWITCH_STATUS_FALSE ;
}
2006-08-25 23:55:59 +00:00
}
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
/* Move Channel's State Machine to RING */
switch_channel_set_state ( channel , CS_RING ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t sofia_on_ring ( switch_core_session_t * session )
{
switch_channel_t * channel = NULL ;
private_object_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " SOFIA RING \n " ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t sofia_on_execute ( switch_core_session_t * session )
{
switch_channel_t * channel = NULL ;
private_object_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " SOFIA EXECUTE \n " ) ;
return SWITCH_STATUS_SUCCESS ;
}
2006-10-25 03:45:20 +00:00
// map QSIG cause codes to SIP from RFC4497 section 8.4.1
2007-03-29 22:31:56 +00:00
static int hangup_cause_to_sip ( switch_call_cause_t cause )
{
2006-09-12 22:24:39 +00:00
switch ( cause ) {
2006-10-25 04:28:49 +00:00
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 :
return 480 ;
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 :
return 502 ;
case SWITCH_CAUSE_INVALID_NUMBER_FORMAT :
return 484 ;
case SWITCH_CAUSE_FACILITY_REJECTED :
return 501 ;
case SWITCH_CAUSE_NORMAL_UNSPECIFIED :
return 480 ;
2007-02-09 20:03:07 +00:00
case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL :
2006-10-25 04:28:49 +00:00
case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION :
case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER :
case SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE :
case SWITCH_CAUSE_SWITCH_CONGESTION :
return 503 ;
case SWITCH_CAUSE_OUTGOING_CALL_BARRED :
case SWITCH_CAUSE_INCOMING_CALL_BARRED :
2007-03-29 22:31:56 +00:00
case SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH :
2006-10-25 04:28:49 +00:00
return 403 ;
case SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL :
return 503 ;
case SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL :
return 488 ;
case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED :
case SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED :
return 501 ;
case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION :
return 503 ;
case SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE :
return 504 ;
case SWITCH_CAUSE_ORIGINATOR_CANCEL :
return 487 ;
default :
2006-12-06 17:19:07 +00:00
return 480 ;
2006-09-12 22:24:39 +00:00
}
}
2006-08-25 23:55:59 +00:00
static switch_status_t sofia_on_hangup ( switch_core_session_t * session )
{
2006-12-28 19:38:35 +00:00
switch_core_session_t * a_session ;
2006-08-25 23:55:59 +00:00
private_object_t * tech_pvt ;
switch_channel_t * channel = NULL ;
2006-09-12 22:24:39 +00:00
switch_call_cause_t cause ;
int sip_cause ;
2006-08-25 23:55:59 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2006-10-25 14:01:03 +00:00
cause = switch_channel_get_cause ( channel ) ;
sip_cause = hangup_cause_to_sip ( cause ) ;
deactivate_rtp ( tech_pvt ) ;
2006-08-28 16:40:05 +00:00
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Channel %s hanging up, cause: %s \n " ,
2007-02-14 03:24:20 +00:00
switch_channel_get_name ( channel ) , switch_channel_cause2str ( cause ) ) ;
2006-08-28 16:40:05 +00:00
2006-10-18 22:57:35 +00:00
if ( tech_pvt - > hash_key ) {
switch_core_hash_delete ( tech_pvt - > profile - > chat_hash , tech_pvt - > hash_key ) ;
}
2006-10-06 22:39:49 +00:00
2006-12-28 19:38:35 +00:00
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 ) ;
2006-10-06 22:39:49 +00:00
switch_channel_hangup ( a_channel , switch_channel_get_cause ( channel ) ) ;
2006-12-28 19:38:35 +00:00
switch_core_session_rwunlock ( a_session ) ;
2006-10-06 22:39:49 +00:00
}
2006-08-25 23:55:59 +00:00
if ( tech_pvt - > nh ) {
if ( ! switch_test_flag ( tech_pvt , TFLAG_BYE ) ) {
2006-09-08 03:28:49 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_ANS ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Sending BYE to %s \n " , switch_channel_get_name ( channel ) ) ;
2006-09-08 03:28:49 +00:00
nua_bye ( tech_pvt - > nh , TAG_END ( ) ) ;
} else {
2006-10-31 21:38:06 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_OUTBOUND ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Responding to INVITE with: %d \n " , sip_cause ) ;
2006-09-12 22:24:39 +00:00
nua_respond ( tech_pvt - > nh , sip_cause , NULL , TAG_END ( ) ) ;
2006-09-18 16:32:47 +00:00
} else {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Sending CANCEL to %s \n " , switch_channel_get_name ( channel ) ) ;
2006-09-12 22:24:39 +00:00
nua_cancel ( tech_pvt - > nh , TAG_END ( ) ) ;
2006-09-18 16:32:47 +00:00
}
2006-09-08 03:28:49 +00:00
}
2006-10-26 20:02:57 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_BYE ) ;
2006-08-25 23:55:59 +00:00
}
}
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
2006-10-25 14:01:03 +00:00
if ( tech_pvt - > home ) {
2006-11-20 21:45:00 +00:00
su_home_unref ( tech_pvt - > home ) ;
2006-10-25 14:01:03 +00:00
tech_pvt - > home = NULL ;
}
2007-03-29 22:31:56 +00:00
if ( tech_pvt - > sofia_private ) {
* tech_pvt - > sofia_private - > uuid = ' \0 ' ;
}
2006-12-28 01:08:06 +00:00
2006-08-25 23:55:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t sofia_on_loopback ( switch_core_session_t * session )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " SOFIA LOOPBACK \n " ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t sofia_on_transmit ( switch_core_session_t * session )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " SOFIA TRANSMIT \n " ) ;
return SWITCH_STATUS_SUCCESS ;
}
2007-03-29 22:31:56 +00:00
static void deactivate_rtp ( private_object_t * tech_pvt )
2006-08-25 23:55:59 +00:00
{
2007-03-29 22:31:56 +00:00
int loops = 0 ; //, sock = -1;
2006-08-28 23:05:26 +00:00
if ( switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
2006-08-25 23:55:59 +00:00
while ( loops < 10 & & ( switch_test_flag ( tech_pvt , TFLAG_READING ) | | switch_test_flag ( tech_pvt , TFLAG_WRITING ) ) ) {
switch_yield ( 10000 ) ;
loops + + ;
}
switch_rtp_destroy ( & tech_pvt - > rtp_session ) ;
}
}
2007-03-29 22:31:56 +00:00
static switch_status_t tech_set_codec ( private_object_t * tech_pvt , int force )
2006-08-25 23:55:59 +00:00
{
switch_channel_t * channel ;
2006-08-29 21:07:24 +00:00
if ( tech_pvt - > read_codec . implementation ) {
2006-10-24 21:31:39 +00:00
if ( ! force ) {
return SWITCH_STATUS_SUCCESS ;
}
2006-09-30 19:17:35 +00:00
if ( strcasecmp ( tech_pvt - > read_codec . implementation - > iananame , tech_pvt - > rm_encoding ) | |
tech_pvt - > read_codec . implementation - > samples_per_second ! = tech_pvt - > rm_rate ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Changing Codec from %s to %s \n " ,
tech_pvt - > read_codec . implementation - > iananame , tech_pvt - > rm_encoding ) ;
2007-03-29 22:31:56 +00:00
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
switch_core_session_reset ( tech_pvt - > session ) ;
2006-09-30 19:17:35 +00:00
} else {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Already using %s \n " , tech_pvt - > read_codec . implementation - > iananame ) ;
2006-09-30 19:17:35 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-08-25 23:55:59 +00:00
}
2006-08-29 21:07:24 +00:00
channel = switch_core_session_get_channel ( tech_pvt - > session ) ;
assert ( channel ! = NULL ) ;
2006-08-25 23:55:59 +00:00
2007-01-27 04:45:54 +00:00
if ( ! tech_pvt - > rm_encoding ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec with no name? \n " ) ;
terminate_session ( & tech_pvt - > session , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER , __LINE__ ) ;
return SWITCH_STATUS_FALSE ;
}
2007-03-29 22:31:56 +00:00
if ( switch_core_codec_init ( & tech_pvt - > read_codec ,
2006-08-25 23:55:59 +00:00
tech_pvt - > rm_encoding ,
2006-10-09 02:24:43 +00:00
tech_pvt - > rm_fmtp ,
2006-08-25 23:55:59 +00:00
tech_pvt - > rm_rate ,
tech_pvt - > codec_ms ,
1 ,
2006-09-02 23:04:25 +00:00
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | tech_pvt - > profile - > codec_flags ,
2007-03-29 22:31:56 +00:00
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
2006-08-25 23:55:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
2006-08-26 21:13:56 +00:00
terminate_session ( & tech_pvt - > session , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER , __LINE__ ) ;
2006-08-25 23:55:59 +00:00
return SWITCH_STATUS_FALSE ;
} else {
if ( switch_core_codec_init ( & tech_pvt - > write_codec ,
tech_pvt - > rm_encoding ,
2006-10-09 02:24:43 +00:00
tech_pvt - > rm_fmtp ,
2006-08-25 23:55:59 +00:00
tech_pvt - > rm_rate ,
tech_pvt - > codec_ms ,
1 ,
2006-09-02 23:04:25 +00:00
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | tech_pvt - > profile - > codec_flags ,
2007-03-29 22:31:56 +00:00
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
2006-08-25 23:55:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
2006-08-26 21:13:56 +00:00
terminate_session ( & tech_pvt - > session , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER , __LINE__ ) ;
2006-08-25 23:55:59 +00:00
return SWITCH_STATUS_FALSE ;
} else {
int ms ;
2006-09-23 18:32:39 +00:00
tech_pvt - > read_frame . rate = tech_pvt - > rm_rate ;
2006-08-25 23:55:59 +00:00
ms = tech_pvt - > write_codec . implementation - > microseconds_per_frame / 1000 ;
2007-03-09 23:51:52 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Set Codec %s %s/%ld %d ms \n " ,
2007-03-30 00:13:31 +00:00
switch_channel_get_name ( channel ) , tech_pvt - > rm_encoding , tech_pvt - > rm_rate , tech_pvt - > codec_ms ) ;
2006-08-25 23:55:59 +00:00
tech_pvt - > read_frame . codec = & tech_pvt - > read_codec ;
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
switch_core_session_set_read_codec ( tech_pvt - > session , & tech_pvt - > read_codec ) ;
switch_core_session_set_write_codec ( tech_pvt - > session , & tech_pvt - > write_codec ) ;
2006-10-09 02:24:43 +00:00
tech_pvt - > fmtp_out = switch_core_session_strdup ( tech_pvt - > session , tech_pvt - > write_codec . fmtp_out ) ;
2006-08-25 23:55:59 +00:00
}
}
2006-08-29 21:07:24 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-08-25 23:55:59 +00:00
2007-03-29 22:31:56 +00:00
static switch_status_t activate_rtp ( private_object_t * tech_pvt )
2006-08-29 21:07:24 +00:00
{
int bw , ms ;
switch_channel_t * channel ;
const char * err = NULL ;
2007-03-29 22:31:56 +00:00
char * val = NULL ;
2006-08-29 21:07:24 +00:00
switch_rtp_flag_t flags ;
switch_status_t status ;
2006-10-31 21:38:06 +00:00
char tmp [ 50 ] ;
2006-08-29 21:07:24 +00:00
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( tech_pvt - > session ) ;
assert ( channel ! = NULL ) ;
2006-10-06 22:39:49 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_NOMEDIA ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2006-08-29 21:07:24 +00:00
2006-09-30 19:17:35 +00:00
if ( switch_rtp_ready ( tech_pvt - > rtp_session ) & & ! switch_test_flag ( tech_pvt , TFLAG_REINVITE ) ) {
2006-08-29 21:07:24 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-10-24 21:31:39 +00:00
if ( ( status = tech_set_codec ( tech_pvt , 0 ) ) ! = SWITCH_STATUS_SUCCESS ) {
2006-08-29 21:07:24 +00:00
return status ;
}
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
bw = tech_pvt - > read_codec . implementation - > bits_per_second ;
ms = tech_pvt - > read_codec . implementation - > microseconds_per_frame ;
2006-09-22 13:43:33 +00:00
flags = ( switch_rtp_flag_t ) ( SWITCH_RTP_FLAG_RAW_WRITE | SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT ) ;
2006-08-25 23:55:59 +00:00
2006-10-12 20:37:08 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_BUGGY_2833 ) ) {
flags | = SWITCH_RTP_FLAG_BUGGY_2833 ;
}
2007-03-29 22:31:56 +00:00
if ( ( tech_pvt - > profile - > pflags & PFLAG_PASS_RFC2833 )
| | ( ( val = switch_channel_get_variable ( channel , " pass_rfc2833 " ) ) & & switch_true ( val ) ) ) {
flags | = SWITCH_RTP_FLAG_PASS_RFC2833 ;
}
2007-01-28 02:38:52 +00:00
2007-03-07 18:34:22 +00:00
if ( tech_pvt - > cng_pt ) {
flags | = SWITCH_RTP_FLAG_AUTO_CNG ;
}
2006-08-25 23:55:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " RTP [%s] %s:%d->%s:%d codec: %u ms: %d \n " ,
switch_channel_get_name ( channel ) ,
tech_pvt - > local_sdp_audio_ip ,
tech_pvt - > local_sdp_audio_port ,
tech_pvt - > remote_sdp_audio_ip ,
2007-03-30 00:13:31 +00:00
tech_pvt - > remote_sdp_audio_port , tech_pvt - > agreed_pt , tech_pvt - > read_codec . implementation - > microseconds_per_frame / 1000 ) ;
2006-08-25 23:55:59 +00:00
2006-10-31 21:38:06 +00:00
snprintf ( tmp , sizeof ( tmp ) , " %d " , tech_pvt - > remote_sdp_audio_port ) ;
switch_channel_set_variable ( channel , SWITCH_LOCAL_MEDIA_IP_VARIABLE , tech_pvt - > adv_sdp_audio_ip ) ;
switch_channel_set_variable ( channel , SWITCH_LOCAL_MEDIA_PORT_VARIABLE , tmp ) ;
2007-03-29 22:31:56 +00:00
2006-09-30 19:17:35 +00:00
if ( tech_pvt - > rtp_session & & switch_test_flag ( tech_pvt , TFLAG_REINVITE ) ) {
switch_clear_flag_locked ( tech_pvt , TFLAG_REINVITE ) ;
2007-03-29 22:31:56 +00:00
2007-03-30 00:13:31 +00:00
if ( switch_rtp_set_remote_address ( tech_pvt - > rtp_session , tech_pvt - > remote_sdp_audio_ip , tech_pvt - > remote_sdp_audio_port , & err ) ! = SWITCH_STATUS_SUCCESS ) {
2006-09-30 19:17:35 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " RTP REPORTS ERROR: [%s] \n " , err ) ;
} else {
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " RTP CHANGING DEST TO: [%s:%d] \n " ,
2006-09-30 19:17:35 +00:00
tech_pvt - > remote_sdp_audio_ip , tech_pvt - > remote_sdp_audio_port ) ;
2007-03-29 22:31:56 +00:00
/* Reactivate the NAT buster flag. */
switch_rtp_set_flag ( tech_pvt - > rtp_session , SWITCH_RTP_FLAG_AUTOADJ ) ;
2006-09-30 19:17:35 +00:00
}
return SWITCH_STATUS_SUCCESS ;
}
2006-08-25 23:55:59 +00:00
tech_pvt - > rtp_session = switch_rtp_new ( tech_pvt - > local_sdp_audio_ip ,
tech_pvt - > local_sdp_audio_port ,
tech_pvt - > remote_sdp_audio_ip ,
tech_pvt - > remote_sdp_audio_port ,
2006-10-30 15:27:05 +00:00
tech_pvt - > agreed_pt ,
2007-03-08 22:18:33 +00:00
tech_pvt - > read_codec . implementation - > samples_per_frame ,
2006-08-25 23:55:59 +00:00
tech_pvt - > codec_ms * 1000 ,
( switch_rtp_flag_t ) flags ,
2007-03-30 00:13:31 +00:00
NULL , tech_pvt - > profile - > timer_name , & err , switch_core_session_get_pool ( tech_pvt - > session ) ) ;
2007-03-29 22:31:56 +00:00
2006-08-28 23:05:26 +00:00
if ( switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
2006-08-25 23:55:59 +00:00
uint8_t vad_in = switch_test_flag ( tech_pvt , TFLAG_VAD_IN ) ? 1 : 0 ;
uint8_t vad_out = switch_test_flag ( tech_pvt , TFLAG_VAD_OUT ) ? 1 : 0 ;
uint8_t inb = switch_test_flag ( tech_pvt , TFLAG_OUTBOUND ) ? 0 : 1 ;
tech_pvt - > ssrc = switch_rtp_get_ssrc ( tech_pvt - > rtp_session ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_RTP ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_IO ) ;
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
if ( ( vad_in & & inb ) | | ( vad_out & & ! inb ) ) {
2007-03-30 00:13:31 +00:00
switch_rtp_enable_vad ( tech_pvt - > rtp_session , tech_pvt - > session , & tech_pvt - > read_codec , SWITCH_VAD_FLAG_TALKING ) ;
2006-08-25 23:55:59 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_VAD ) ;
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " RTP Engage VAD for %s ( %s %s ) \n " ,
2007-03-30 00:13:31 +00:00
switch_channel_get_name ( switch_core_session_get_channel ( tech_pvt - > session ) ) , vad_in ? " in " : " " , vad_out ? " out " : " " ) ;
2006-08-25 23:55:59 +00:00
}
2007-03-07 18:34:22 +00:00
2007-03-09 01:15:54 +00:00
if ( tech_pvt - > te ) {
switch_rtp_set_telephony_event ( tech_pvt - > rtp_session , tech_pvt - > te ) ;
}
2007-03-07 18:34:22 +00:00
if ( tech_pvt - > cng_pt ) {
switch_rtp_set_cng_pt ( tech_pvt - > rtp_session , tech_pvt - > cng_pt ) ;
}
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " RTP REPORTS ERROR: [%s] \n " , err ) ;
2006-08-26 21:13:56 +00:00
terminate_session ( & tech_pvt - > session , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER , __LINE__ ) ;
2006-08-25 23:55:59 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
return SWITCH_STATUS_FALSE ;
}
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_IO ) ;
return SWITCH_STATUS_SUCCESS ;
}
2007-03-29 22:31:56 +00:00
static switch_status_t tech_media ( private_object_t * tech_pvt , char * r_sdp )
2007-01-20 18:51:57 +00:00
{
2007-03-29 22:31:56 +00:00
sdp_parser_t * parser = sdp_parse ( tech_pvt - > home , r_sdp , ( int ) strlen ( r_sdp ) , 0 ) ;
sdp_session_t * sdp ;
uint8_t match = 0 ;
switch_channel_t * channel = switch_core_session_get_channel ( tech_pvt - > session ) ;
assert ( tech_pvt ! = NULL ) ;
if ( switch_strlen_zero ( r_sdp ) ) {
return SWITCH_STATUS_FALSE ;
}
if ( tech_pvt - > num_codecs ) {
if ( ( sdp = sdp_session ( parser ) ) ) {
match = negotiate_sdp ( tech_pvt - > session , sdp ) ;
}
}
if ( parser ) {
sdp_parser_free ( parser ) ;
}
if ( match ) {
if ( tech_choose_port ( tech_pvt ) ! = SWITCH_STATUS_SUCCESS ) {
return SWITCH_STATUS_FALSE ;
}
activate_rtp ( tech_pvt ) ;
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " EARLY MEDIA " ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_EARLY_MEDIA ) ;
switch_channel_mark_pre_answered ( channel ) ;
return SWITCH_STATUS_SUCCESS ;
}
return SWITCH_STATUS_FALSE ;
2007-01-20 18:51:57 +00:00
}
2006-08-25 23:55:59 +00:00
static switch_status_t sofia_answer_channel ( switch_core_session_t * session )
{
private_object_t * tech_pvt ;
switch_channel_t * channel = NULL ;
2007-01-15 16:59:42 +00:00
switch_status_t status ;
2006-08-25 23:55:59 +00:00
assert ( session ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_ANS ) & & ! switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_ANS ) ;
2006-10-06 22:39:49 +00:00
2007-02-10 19:34:03 +00:00
if ( switch_channel_test_flag ( channel , CF_NOMEDIA ) ) {
char * sdp = NULL ;
switch_set_flag_locked ( tech_pvt , TFLAG_NOMEDIA ) ;
if ( ( sdp = switch_channel_get_variable ( channel , SWITCH_B_SDP_VARIABLE ) ) ) {
tech_pvt - > local_sdp_str = switch_core_session_strdup ( session , sdp ) ;
}
} else {
if ( switch_test_flag ( tech_pvt , TFLAG_LATE_NEGOTIATION ) ) {
char * r_sdp = switch_channel_get_variable ( channel , SWITCH_R_SDP_VARIABLE ) ;
if ( tech_media ( tech_pvt , r_sdp ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " CODEC NEGOTIATION ERROR " ) ;
2007-02-10 19:34:03 +00:00
nua_respond ( tech_pvt - > nh , SIP_488_NOT_ACCEPTABLE , TAG_END ( ) ) ;
return SWITCH_STATUS_FALSE ;
}
switch_clear_flag_locked ( tech_pvt , TFLAG_LATE_NEGOTIATION ) ;
}
2006-10-06 22:39:49 +00:00
2007-02-10 19:34:03 +00:00
if ( ( status = tech_choose_port ( tech_pvt ) ) ! = SWITCH_STATUS_SUCCESS ) {
return status ;
}
2007-01-15 16:59:42 +00:00
2007-02-10 19:34:03 +00:00
set_local_sdp ( tech_pvt , NULL , 0 , NULL , 0 ) ;
activate_rtp ( tech_pvt ) ;
2007-03-29 22:31:56 +00:00
2007-02-10 19:34:03 +00:00
if ( tech_pvt - > nh ) {
if ( tech_pvt - > local_sdp_str ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Local SDP %s: \n %s \n " , switch_channel_get_name ( channel ) , tech_pvt - > local_sdp_str ) ;
2007-02-10 19:34:03 +00:00
}
2007-02-06 18:27:02 +00:00
}
2006-08-25 23:55:59 +00:00
}
2007-03-29 22:31:56 +00:00
nua_respond ( tech_pvt - > nh , SIP_200_OK ,
2007-02-10 19:34:03 +00:00
SIPTAG_CONTACT_STR ( tech_pvt - > profile - > url ) ,
2007-03-30 00:13:31 +00:00
SOATAG_USER_SDP_STR ( tech_pvt - > local_sdp_str ) , SOATAG_AUDIO_AUX ( " cn telephone-event " ) , NUTAG_INCLUDE_EXTRA_SDP ( 1 ) , TAG_END ( ) ) ;
2007-03-29 22:31:56 +00:00
}
2006-08-25 23:55:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-03-30 00:13:31 +00:00
static switch_status_t sofia_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , int timeout , switch_io_flag_t flags , int stream_id )
2006-08-25 23:55:59 +00:00
{
private_object_t * tech_pvt = NULL ;
switch_channel_t * channel = NULL ;
int payload = 0 ;
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
if ( switch_test_flag ( tech_pvt , TFLAG_HUP ) ) {
return SWITCH_STATUS_FALSE ;
}
2006-10-31 21:38:06 +00:00
while ( ! ( tech_pvt - > read_codec . implementation & & switch_rtp_ready ( tech_pvt - > rtp_session ) ) ) {
if ( switch_channel_ready ( channel ) ) {
switch_yield ( 10000 ) ;
} else {
return SWITCH_STATUS_GENERR ;
}
}
2006-08-25 23:55:59 +00:00
tech_pvt - > read_frame . datalen = 0 ;
switch_set_flag_locked ( tech_pvt , TFLAG_READING ) ;
2007-03-29 22:31:56 +00:00
#if 0
2006-08-25 23:55:59 +00:00
if ( tech_pvt - > last_read ) {
2007-03-29 22:31:56 +00:00
elapsed = ( unsigned int ) ( ( switch_time_now ( ) - tech_pvt - > last_read ) / 1000 ) ;
2006-08-25 23:55:59 +00:00
if ( elapsed > 60000 ) {
return SWITCH_STATUS_TIMEOUT ;
}
}
2006-12-18 21:40:04 +00:00
# endif
2006-08-25 23:55:59 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
switch_status_t status ;
if ( ! switch_test_flag ( tech_pvt , TFLAG_RTP ) ) {
return SWITCH_STATUS_GENERR ;
}
assert ( tech_pvt - > rtp_session ! = NULL ) ;
tech_pvt - > read_frame . datalen = 0 ;
2006-12-28 01:08:06 +00:00
while ( switch_test_flag ( tech_pvt , TFLAG_IO ) & & tech_pvt - > read_frame . datalen = = 0 ) {
2006-08-25 23:55:59 +00:00
tech_pvt - > read_frame . flags = SFF_NONE ;
status = switch_rtp_zerocopy_read_frame ( tech_pvt - > rtp_session , & tech_pvt - > read_frame ) ;
if ( status ! = SWITCH_STATUS_SUCCESS & & status ! = SWITCH_STATUS_BREAK ) {
return SWITCH_STATUS_FALSE ;
}
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
payload = tech_pvt - > read_frame . payload ;
2006-09-17 21:57:20 +00:00
#if 0
2007-03-29 22:31:56 +00:00
elapsed = ( unsigned int ) ( ( switch_time_now ( ) - started ) / 1000 ) ;
2006-08-25 23:55:59 +00:00
if ( timeout > - 1 ) {
2007-03-29 22:31:56 +00:00
if ( elapsed > = ( unsigned int ) timeout ) {
2006-08-25 23:55:59 +00:00
return SWITCH_STATUS_BREAK ;
}
}
2007-03-29 22:31:56 +00:00
elapsed = ( unsigned int ) ( ( switch_time_now ( ) - last_act ) / 1000 ) ;
2006-08-25 23:55:59 +00:00
if ( elapsed > = hard_timeout ) {
return SWITCH_STATUS_BREAK ;
}
2006-09-17 21:57:20 +00:00
# endif
2006-08-25 23:55:59 +00:00
if ( switch_rtp_has_dtmf ( tech_pvt - > rtp_session ) ) {
char dtmf [ 128 ] ;
switch_rtp_dequeue_dtmf ( tech_pvt - > rtp_session , dtmf , sizeof ( dtmf ) ) ;
switch_channel_queue_dtmf ( channel , dtmf ) ;
}
if ( tech_pvt - > read_frame . datalen > 0 ) {
2007-03-29 22:31:56 +00:00
size_t bytes = 0 ;
int frames = 1 ;
if ( ! switch_test_flag ( ( & tech_pvt - > read_frame ) , SFF_CNG ) ) {
if ( ( bytes = tech_pvt - > read_codec . implementation - > encoded_bytes_per_frame ) ) {
frames = ( tech_pvt - > read_frame . datalen / bytes ) ;
}
2007-03-30 00:13:31 +00:00
tech_pvt - > read_frame . samples = ( int ) ( frames * tech_pvt - > read_codec . implementation - > samples_per_frame ) ;
2007-03-29 22:31:56 +00:00
}
2006-08-25 23:55:59 +00:00
break ;
}
}
2006-12-18 21:40:04 +00:00
}
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_READING ) ;
2006-09-14 21:12:39 +00:00
if ( tech_pvt - > read_frame . datalen = = 0 ) {
* frame = NULL ;
return SWITCH_STATUS_GENERR ;
}
2006-08-25 23:55:59 +00:00
* frame = & tech_pvt - > read_frame ;
return SWITCH_STATUS_SUCCESS ;
}
2007-03-30 00:13:31 +00:00
static switch_status_t sofia_write_frame ( switch_core_session_t * session , switch_frame_t * frame , int timeout , switch_io_flag_t flags , int stream_id )
2006-08-25 23:55:59 +00:00
{
private_object_t * tech_pvt ;
switch_channel_t * channel = NULL ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
int bytes = 0 , samples = 0 , frames = 0 ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2006-10-31 21:38:06 +00:00
while ( ! ( tech_pvt - > read_codec . implementation & & switch_rtp_ready ( tech_pvt - > rtp_session ) ) ) {
if ( switch_channel_ready ( channel ) ) {
switch_yield ( 10000 ) ;
} else {
return SWITCH_STATUS_GENERR ;
}
}
2006-08-25 23:55:59 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_HUP ) ) {
return SWITCH_STATUS_FALSE ;
}
if ( ! switch_test_flag ( tech_pvt , TFLAG_RTP ) ) {
return SWITCH_STATUS_GENERR ;
}
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
return SWITCH_STATUS_SUCCESS ;
}
switch_set_flag_locked ( tech_pvt , TFLAG_WRITING ) ;
2007-03-07 21:21:42 +00:00
if ( ! switch_test_flag ( frame , SFF_CNG ) ) {
if ( tech_pvt - > read_codec . implementation - > encoded_bytes_per_frame ) {
bytes = tech_pvt - > read_codec . implementation - > encoded_bytes_per_frame ;
frames = ( ( int ) frame - > datalen / bytes ) ;
} else
frames = 1 ;
2006-08-25 23:55:59 +00:00
2007-03-07 21:21:42 +00:00
samples = frames * tech_pvt - > read_codec . implementation - > samples_per_frame ;
}
2006-08-25 23:55:59 +00:00
#if 0
printf ( " %s %s->%s send %d bytes %d samples in %d frames ts=%d \n " ,
switch_channel_get_name ( channel ) ,
2007-03-30 00:13:31 +00:00
tech_pvt - > local_sdp_audio_ip , tech_pvt - > remote_sdp_audio_ip , frame - > datalen , samples , frames , tech_pvt - > timestamp_send ) ;
2006-08-25 23:55:59 +00:00
# endif
2007-03-05 20:53:54 +00:00
tech_pvt - > timestamp_send + = samples ;
2007-03-07 18:34:22 +00:00
//switch_rtp_write_frame(tech_pvt->rtp_session, frame, tech_pvt->timestamp_send);
switch_rtp_write_frame ( tech_pvt - > rtp_session , frame , 0 ) ;
2006-08-25 23:55:59 +00:00
switch_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_channel_t * channel = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-03-29 22:31:56 +00:00
switch ( sig ) {
case SWITCH_SIG_BREAK :
if ( switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
2007-02-10 19:34:03 +00:00
switch_rtp_set_flag ( tech_pvt - > rtp_session , SWITCH_RTP_FLAG_BREAK ) ;
}
2007-03-29 22:31:56 +00:00
break ;
case SWITCH_SIG_KILL :
default :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_HUP ) ;
2006-12-18 21:40:04 +00:00
2007-03-29 22:31:56 +00:00
if ( switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
switch_rtp_kill_socket ( tech_pvt - > rtp_session ) ;
}
break ;
}
2006-08-25 23:55:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t sofia_waitfor_read ( switch_core_session_t * session , int ms , int stream_id )
{
private_object_t * tech_pvt ;
switch_channel_t * channel = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t sofia_waitfor_write ( switch_core_session_t * session , int ms , int stream_id )
{
private_object_t * tech_pvt ;
switch_channel_t * channel = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t sofia_send_dtmf ( switch_core_session_t * session , char * digits )
{
private_object_t * tech_pvt ;
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
2007-03-29 22:31:56 +00:00
assert ( tech_pvt ! = NULL ) ;
2006-08-25 23:55:59 +00:00
return switch_rtp_queue_rfc2833 ( tech_pvt - > rtp_session ,
2007-03-30 00:13:31 +00:00
digits , tech_pvt - > profile - > dtmf_duration * ( tech_pvt - > read_codec . implementation - > samples_per_second / 1000 ) ) ;
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
}
static switch_status_t sofia_receive_message ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_object_t * tech_pvt ;
2007-03-29 22:31:56 +00:00
switch_status_t status ;
2007-01-15 16:59:42 +00:00
2006-08-25 23:55:59 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch ( msg - > message_id ) {
2007-03-29 22:31:56 +00:00
case SWITCH_MESSAGE_INDICATE_NOMEDIA : {
char * uuid ;
switch_core_session_t * other_session ;
switch_channel_t * other_channel ;
char * ip = NULL , * port = NULL ;
2006-10-31 21:38:06 +00:00
2007-03-29 22:31:56 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_NOMEDIA ) ;
tech_pvt - > local_sdp_str = NULL ;
if ( ( uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) )
& & ( other_session = switch_core_session_locate ( uuid ) ) ) {
other_channel = switch_core_session_get_channel ( other_session ) ;
ip = switch_channel_get_variable ( other_channel , SWITCH_REMOTE_MEDIA_IP_VARIABLE ) ;
port = switch_channel_get_variable ( other_channel , SWITCH_REMOTE_MEDIA_PORT_VARIABLE ) ;
switch_core_session_rwunlock ( other_session ) ;
if ( ip & & port ) {
set_local_sdp ( tech_pvt , ip , atoi ( port ) , NULL , 1 ) ;
}
2006-10-31 21:38:06 +00:00
}
2007-03-29 22:31:56 +00:00
if ( ! tech_pvt - > local_sdp_str ) {
tech_absorb_sdp ( tech_pvt ) ;
}
do_invite ( session ) ;
2006-10-31 21:38:06 +00:00
}
break ;
2007-03-29 22:31:56 +00:00
case SWITCH_MESSAGE_INDICATE_MEDIA : {
switch_clear_flag_locked ( tech_pvt , TFLAG_NOMEDIA ) ;
tech_pvt - > local_sdp_str = NULL ;
if ( ! switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
tech_set_codecs ( tech_pvt ) ;
if ( ( status = tech_choose_port ( tech_pvt ) ) ! = SWITCH_STATUS_SUCCESS ) {
return status ;
}
}
set_local_sdp ( tech_pvt , NULL , 0 , NULL , 1 ) ;
do_invite ( session ) ;
while ( ! switch_rtp_ready ( tech_pvt - > rtp_session ) & & switch_channel_get_state ( channel ) < CS_HANGUP ) {
switch_yield ( 1000 ) ;
}
2006-11-09 16:26:12 +00:00
}
2006-10-31 21:38:06 +00:00
break ;
2007-03-29 22:31:56 +00:00
case SWITCH_MESSAGE_INDICATE_HOLD : {
switch_set_flag_locked ( tech_pvt , TFLAG_SIP_HOLD ) ;
do_invite ( session ) ;
}
2006-10-31 21:38:06 +00:00
break ;
2007-03-29 22:31:56 +00:00
case SWITCH_MESSAGE_INDICATE_UNHOLD : {
switch_clear_flag_locked ( tech_pvt , TFLAG_SIP_HOLD ) ;
do_invite ( session ) ;
}
2006-10-31 21:38:06 +00:00
break ;
2006-08-25 23:55:59 +00:00
case SWITCH_MESSAGE_INDICATE_BRIDGE :
2006-10-06 22:39:49 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_XFER ) ) {
switch_clear_flag_locked ( tech_pvt , TFLAG_XFER ) ;
if ( msg - > pointer_arg ) {
2006-12-28 19:38:35 +00:00
switch_core_session_t * a_session , * b_session = msg - > pointer_arg ;
2006-10-06 22:39:49 +00:00
2006-12-28 19:38:35 +00:00
if ( ( a_session = switch_core_session_locate ( tech_pvt - > xferto ) ) ) {
private_object_t * a_tech_pvt = switch_core_session_get_private ( a_session ) ;
private_object_t * b_tech_pvt = switch_core_session_get_private ( b_session ) ;
2006-10-06 22:39:49 +00:00
switch_set_flag_locked ( a_tech_pvt , TFLAG_REINVITE ) ;
2007-03-30 00:13:31 +00:00
a_tech_pvt - > remote_sdp_audio_ip = switch_core_session_strdup ( a_session , b_tech_pvt - > remote_sdp_audio_ip ) ;
2006-10-06 22:39:49 +00:00
a_tech_pvt - > remote_sdp_audio_port = b_tech_pvt - > remote_sdp_audio_port ;
2007-03-30 00:13:31 +00:00
a_tech_pvt - > local_sdp_audio_ip = switch_core_session_strdup ( a_session , b_tech_pvt - > local_sdp_audio_ip ) ;
2006-10-06 22:39:49 +00:00
a_tech_pvt - > local_sdp_audio_port = b_tech_pvt - > local_sdp_audio_port ;
activate_rtp ( a_tech_pvt ) ;
2007-03-29 22:31:56 +00:00
2006-12-28 19:38:35 +00:00
b_tech_pvt - > kick = switch_core_session_strdup ( b_session , tech_pvt - > xferto ) ;
2007-03-29 22:31:56 +00:00
switch_core_session_rwunlock ( a_session ) ;
2006-10-06 22:39:49 +00:00
}
2007-03-29 22:31:56 +00:00
2006-10-06 22:39:49 +00:00
msg - > pointer_arg = NULL ;
return SWITCH_STATUS_FALSE ;
}
}
2006-08-26 21:13:56 +00:00
if ( tech_pvt - > rtp_session & & switch_test_flag ( tech_pvt , TFLAG_TIMER ) ) {
switch_rtp_clear_flag ( tech_pvt - > rtp_session , SWITCH_RTP_FLAG_USE_TIMER ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " De-activate timed RTP! \n " ) ;
}
break ;
2006-08-25 23:55:59 +00:00
case SWITCH_MESSAGE_INDICATE_UNBRIDGE :
2006-08-26 21:13:56 +00:00
if ( tech_pvt - > rtp_session & & switch_test_flag ( tech_pvt , TFLAG_TIMER ) ) {
switch_rtp_set_flag ( tech_pvt - > rtp_session , SWITCH_RTP_FLAG_USE_TIMER ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Re-activate timed RTP! \n " ) ;
}
break ;
2007-01-10 21:26:10 +00:00
case SWITCH_MESSAGE_INDICATE_REDIRECT :
2007-03-29 22:31:56 +00:00
if ( msg - > string_arg ) {
2007-01-10 21:26:10 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Re-directing to %s \n " , msg - > string_arg ) ;
nua_respond ( tech_pvt - > nh , SIP_302_MOVED_TEMPORARILY , SIPTAG_CONTACT_STR ( msg - > string_arg ) , TAG_END ( ) ) ;
}
break ;
2006-10-12 00:59:09 +00:00
case SWITCH_MESSAGE_INDICATE_RINGING :
2006-11-09 17:19:15 +00:00
nua_respond ( tech_pvt - > nh , SIP_180_RINGING , SIPTAG_CONTACT_STR ( tech_pvt - > profile - > url ) , TAG_END ( ) ) ;
2006-10-12 00:59:09 +00:00
break ;
2007-03-29 22:31:56 +00:00
case SWITCH_MESSAGE_INDICATE_PROGRESS : {
if ( ! switch_test_flag ( tech_pvt , TFLAG_ANS ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_EARLY_MEDIA ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Asked to send early media by %s \n " , msg - > from ) ;
/* Transmit 183 Progress with SDP */
if ( switch_channel_test_flag ( channel , CF_NOMEDIA ) ) {
char * sdp = NULL ;
switch_set_flag_locked ( tech_pvt , TFLAG_NOMEDIA ) ;
if ( ( sdp = switch_channel_get_variable ( channel , SWITCH_B_SDP_VARIABLE ) ) ) {
tech_pvt - > local_sdp_str = switch_core_session_strdup ( session , sdp ) ;
}
} else {
if ( switch_test_flag ( tech_pvt , TFLAG_LATE_NEGOTIATION ) ) {
char * r_sdp = switch_channel_get_variable ( channel , SWITCH_R_SDP_VARIABLE ) ;
if ( tech_media ( tech_pvt , r_sdp ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " CODEC NEGOTIATION ERROR " ) ;
2007-03-29 22:31:56 +00:00
nua_respond ( tech_pvt - > nh , SIP_488_NOT_ACCEPTABLE , TAG_END ( ) ) ;
return SWITCH_STATUS_FALSE ;
}
switch_clear_flag_locked ( tech_pvt , TFLAG_LATE_NEGOTIATION ) ;
2007-02-10 19:34:03 +00:00
}
2006-10-31 21:38:06 +00:00
2007-03-29 22:31:56 +00:00
if ( ( status = tech_choose_port ( tech_pvt ) ) ! = SWITCH_STATUS_SUCCESS ) {
return status ;
}
set_local_sdp ( tech_pvt , NULL , 0 , NULL , 0 ) ;
activate_rtp ( tech_pvt ) ;
if ( tech_pvt - > local_sdp_str ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Ring SDP: \n %s \n " , tech_pvt - > local_sdp_str ) ;
2007-03-29 22:31:56 +00:00
}
2007-02-10 19:34:03 +00:00
}
2007-03-29 22:31:56 +00:00
nua_respond ( tech_pvt - > nh ,
SIP_183_SESSION_PROGRESS ,
SIPTAG_CONTACT_STR ( tech_pvt - > profile - > url ) ,
2007-03-30 00:13:31 +00:00
SOATAG_USER_SDP_STR ( tech_pvt - > local_sdp_str ) , SOATAG_AUDIO_AUX ( " cn telephone-event " ) , TAG_END ( ) ) ;
2007-02-10 19:34:03 +00:00
}
2007-03-29 22:31:56 +00:00
}
2006-08-25 23:55:59 +00:00
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2006-10-18 22:57:35 +00:00
static switch_status_t sofia_receive_event ( switch_core_session_t * session , switch_event_t * event )
{
switch_channel_t * channel ;
2007-03-29 22:31:56 +00:00
struct private_object * tech_pvt ;
2006-10-18 22:57:35 +00:00
char * body ;
nua_handle_t * msg_nh ;
2007-03-29 22:31:56 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2006-10-18 22:57:35 +00:00
2007-03-29 22:31:56 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2006-10-18 22:57:35 +00:00
if ( ! ( body = switch_event_get_body ( event ) ) ) {
body = " " ;
}
if ( tech_pvt - > hash_key ) {
msg_nh = nua_handle ( tech_pvt - > profile - > nua , NULL ,
SIPTAG_FROM_STR ( tech_pvt - > chat_from ) ,
2007-03-30 00:13:31 +00:00
NUTAG_URL ( tech_pvt - > chat_to ) , SIPTAG_TO_STR ( tech_pvt - > chat_to ) , SIPTAG_CONTACT_STR ( tech_pvt - > profile - > url ) , TAG_END ( ) ) ;
2006-10-18 22:57:35 +00:00
2007-03-29 22:31:56 +00:00
nua_message ( msg_nh , SIPTAG_CONTENT_TYPE_STR ( " text/html " ) , SIPTAG_PAYLOAD_STR ( body ) , TAG_END ( ) ) ;
2006-10-18 22:57:35 +00:00
}
return SWITCH_STATUS_SUCCESS ;
}
2006-08-25 23:55:59 +00:00
static const switch_io_routines_t sofia_io_routines = {
/*.outgoing_channel */ sofia_outgoing_channel ,
/*.answer_channel */ sofia_answer_channel ,
/*.read_frame */ sofia_read_frame ,
/*.write_frame */ sofia_write_frame ,
/*.kill_channel */ sofia_kill_channel ,
/*.waitfor_read */ sofia_waitfor_read ,
/*.waitfor_read */ sofia_waitfor_write ,
2007-03-29 22:31:56 +00:00
/*.send_dtmf */ sofia_send_dtmf ,
/*.receive_message */ sofia_receive_message ,
/*.receive_event */ sofia_receive_event
2006-08-25 23:55:59 +00:00
} ;
static const switch_state_handler_table_t sofia_event_handlers = {
/*.on_init */ sofia_on_init ,
/*.on_ring */ sofia_on_ring ,
/*.on_execute */ sofia_on_execute ,
/*.on_hangup */ sofia_on_hangup ,
/*.on_loopback */ sofia_on_loopback ,
/*.on_transmit */ sofia_on_transmit
} ;
static const switch_endpoint_interface_t sofia_endpoint_interface = {
/*.interface_name */ " sofia " ,
/*.io_routines */ & sofia_io_routines ,
/*.event_handlers */ & sofia_event_handlers ,
/*.private */ NULL ,
/*.next */ NULL
} ;
2006-10-19 07:13:34 +00:00
static const switch_chat_interface_t sofia_chat_interface = {
2006-10-20 22:11:26 +00:00
/*.name */ SOFIA_CHAT_PROTO ,
2006-10-19 07:13:34 +00:00
/*.chat_send */ chat_send ,
2007-03-29 22:31:56 +00:00
2006-10-19 07:13:34 +00:00
} ;
2007-03-30 00:13:31 +00:00
static switch_status_t sofia_manage ( char * relative_oid , switch_management_action_t action , char * data , switch_size_t datalen )
2007-03-19 15:01:38 +00:00
{
return SWITCH_STATUS_SUCCESS ;
}
static const switch_management_interface_t sofia_management_interface = {
2007-03-29 22:31:56 +00:00
/*.relative_oid */ " 1 " ,
/*.management_function */ sofia_manage
2007-03-19 15:01:38 +00:00
} ;
2006-08-25 23:55:59 +00:00
static const switch_loadable_module_interface_t sofia_module_interface = {
/*.module_name */ modname ,
/*.endpoint_interface */ & sofia_endpoint_interface ,
/*.timer_interface */ NULL ,
/*.dialplan_interface */ NULL ,
/*.codec_interface */ NULL ,
2006-10-19 07:13:34 +00:00
/*.application_interface */ NULL ,
/*.api_interface */ NULL ,
/*.file_interface */ NULL ,
/*.speech_interface */ NULL ,
/*.directory_interface */ NULL ,
2007-03-19 15:01:38 +00:00
/*.chat_interface */ & sofia_chat_interface ,
/*.say_interface */ NULL ,
/*.asr_interface */ NULL ,
/*.management_interface */ & sofia_management_interface
2006-08-25 23:55:59 +00:00
} ;
2006-10-09 17:11:39 +00:00
static void logger ( void * logarg , char const * fmt , va_list ap )
{
2006-10-09 20:04:38 +00:00
char * data = NULL ;
2006-10-09 17:11:39 +00:00
if ( fmt ) {
# ifdef HAVE_VASPRINTF
2006-10-09 20:04:38 +00:00
int ret ;
2006-10-09 17:11:39 +00:00
ret = vasprintf ( & data , fmt , ap ) ;
2006-10-09 20:04:38 +00:00
if ( ( ret = = - 1 ) | | ! data ) {
return ;
}
2006-10-09 17:11:39 +00:00
# else
data = ( char * ) malloc ( 2048 ) ;
2006-10-09 20:04:38 +00:00
if ( data ) {
vsnprintf ( data , 2048 , fmt , ap ) ;
2007-03-29 22:31:56 +00:00
} else {
2006-10-09 17:11:39 +00:00
return ;
}
2006-10-09 20:04:38 +00:00
# endif
2006-10-09 17:11:39 +00:00
}
2007-02-06 18:37:01 +00:00
if ( data ) {
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG_CLEAN , SWITCH_LOG_CONSOLE , ( char * ) " %s " , data ) ;
2007-02-06 18:37:01 +00:00
free ( data ) ;
}
2006-10-09 17:11:39 +00:00
}
2007-03-29 22:31:56 +00:00
static switch_call_cause_t sofia_outgoing_channel ( switch_core_session_t * session ,
2007-03-30 00:13:31 +00:00
switch_caller_profile_t * outbound_profile , switch_core_session_t * * new_session , switch_memory_pool_t * * pool )
2006-08-25 23:55:59 +00:00
{
2007-02-09 20:03:07 +00:00
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
2006-08-25 23:55:59 +00:00
switch_core_session_t * nsession ;
char * data , * profile_name , * dest ;
sofia_profile_t * profile ;
switch_caller_profile_t * caller_profile = NULL ;
private_object_t * tech_pvt = NULL ;
2006-10-06 22:39:49 +00:00
switch_channel_t * nchannel ;
2007-02-13 01:22:17 +00:00
char * host , * dest_to ;
2006-08-25 23:55:59 +00:00
* new_session = NULL ;
if ( ! ( nsession = switch_core_session_request ( & sofia_endpoint_interface , pool ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error Creating Session \n " ) ;
goto done ;
}
if ( ! ( tech_pvt = ( struct private_object * ) switch_core_session_alloc ( nsession , sizeof ( * tech_pvt ) ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error Creating Session \n " ) ;
2006-08-26 21:13:56 +00:00
terminate_session ( & nsession , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER , __LINE__ ) ;
2006-08-25 23:55:59 +00:00
goto done ;
}
data = switch_core_session_strdup ( nsession , outbound_profile - > destination_number ) ;
profile_name = data ;
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( ! strncasecmp ( profile_name , " gateway " , 7 ) ) {
char * gw ;
outbound_reg_t * gateway_ptr ;
2006-08-25 23:55:59 +00:00
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( ! ( gw = strchr ( profile_name , ' / ' ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid URL \n " ) ;
terminate_session ( & nsession , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER , __LINE__ ) ;
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT ;
goto done ;
}
2006-09-27 03:44:14 +00:00
2007-03-19 21:09:53 +00:00
* gw + + = ' \0 ' ;
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( ! ( dest = strchr ( gw , ' / ' ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid URL \n " ) ;
terminate_session ( & nsession , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER , __LINE__ ) ;
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT ;
goto done ;
}
2007-02-13 01:22:17 +00:00
2007-03-19 21:09:53 +00:00
* dest + + = ' \0 ' ;
if ( ! ( gateway_ptr = find_gateway ( gw ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Gateway \n " ) ;
terminate_session ( & nsession , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER , __LINE__ ) ;
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT ;
goto done ;
}
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
profile = gateway_ptr - > profile ;
tech_pvt - > 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 " , dest , gateway_ptr - > register_proxy + 4 ) ;
2006-09-29 01:07:51 +00:00
} else {
2007-03-19 21:09:53 +00:00
tech_pvt - > dest = switch_core_session_sprintf ( nsession , " sip:%s " , dest ) ;
}
} else {
if ( ! ( dest = strchr ( profile_name , ' / ' ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid URL \n " ) ;
terminate_session ( & nsession , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER , __LINE__ ) ;
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT ;
2006-09-29 01:07:51 +00:00
goto done ;
}
2007-03-19 21:09:53 +00:00
* dest + + = ' \0 ' ;
2006-11-13 21:17:57 +00:00
2007-03-19 21:09:53 +00:00
if ( ! ( profile = find_profile ( profile_name ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Profile \n " ) ;
terminate_session ( & nsession , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER , __LINE__ ) ;
2007-03-29 22:31:56 +00:00
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
2007-03-19 21:09:53 +00:00
goto done ;
}
if ( ( dest_to = strchr ( dest , ' ^ ' ) ) ) {
* dest_to + + = ' \0 ' ;
tech_pvt - > dest_to = switch_core_session_alloc ( nsession , strlen ( dest_to ) + 5 ) ;
snprintf ( tech_pvt - > dest_to , strlen ( dest_to ) + 5 , " sip:%s " , dest_to ) ;
}
if ( ( host = strchr ( dest , ' % ' ) ) ) {
char buf [ 128 ] ;
* host = ' @ ' ;
tech_pvt - > e_dest = switch_core_session_strdup ( nsession , dest ) ;
* host + + = ' \0 ' ;
if ( find_reg_url ( profile , dest , host , buf , sizeof ( buf ) ) ) {
tech_pvt - > dest = switch_core_session_strdup ( nsession , buf ) ;
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
} else {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Cannot locate registered user %s@%s \n " , dest , host ) ;
2007-03-19 21:09:53 +00:00
cause = SWITCH_CAUSE_NO_ROUTE_DESTINATION ;
terminate_session ( & nsession , cause , __LINE__ ) ;
goto done ;
}
} else if ( ! strchr ( dest , ' @ ' ) ) {
char buf [ 128 ] ;
tech_pvt - > e_dest = switch_core_session_strdup ( nsession , dest ) ;
if ( find_reg_url ( profile , dest , profile_name , buf , sizeof ( buf ) ) ) {
tech_pvt - > dest = switch_core_session_strdup ( nsession , buf ) ;
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
} else {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Cannot locate registered user %s@%s \n " , dest , profile_name ) ;
2007-03-19 21:09:53 +00:00
cause = SWITCH_CAUSE_NO_ROUTE_DESTINATION ;
terminate_session ( & nsession , cause , __LINE__ ) ;
goto done ;
}
} else {
tech_pvt - > dest = switch_core_session_alloc ( nsession , strlen ( dest ) + 5 ) ;
snprintf ( tech_pvt - > dest , strlen ( dest ) + 5 , " sip:%s " , dest ) ;
}
2006-09-27 03:44:14 +00:00
}
2006-11-13 21:17:57 +00:00
2007-02-13 01:22:17 +00:00
if ( ! tech_pvt - > dest_to ) {
tech_pvt - > dest_to = tech_pvt - > dest ;
}
2006-10-07 22:19:24 +00:00
2007-02-13 01:22:17 +00:00
attach_private ( nsession , profile , tech_pvt , dest ) ;
2007-01-28 17:37:51 +00:00
2006-10-06 22:39:49 +00:00
nchannel = switch_core_session_get_channel ( nsession ) ;
2006-08-25 23:55:59 +00:00
caller_profile = switch_caller_profile_clone ( nsession , outbound_profile ) ;
2006-10-06 22:39:49 +00:00
switch_channel_set_caller_profile ( nchannel , caller_profile ) ;
switch_channel_set_flag ( nchannel , CF_OUTBOUND ) ;
2006-08-25 23:55:59 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_OUTBOUND ) ;
2006-10-06 22:39:49 +00:00
switch_channel_set_state ( nchannel , CS_INIT ) ;
2006-08-25 23:55:59 +00:00
* new_session = nsession ;
2007-02-09 20:03:07 +00:00
cause = SWITCH_CAUSE_SUCCESS ;
2006-10-05 14:24:25 +00:00
if ( session ) {
2006-10-31 21:38:06 +00:00
//char *val;
//switch_channel_t *channel = switch_core_session_get_channel(session);
2006-10-05 14:24:25 +00:00
switch_ivr_transfer_variable ( session , nsession , SOFIA_REPLACES_HEADER ) ;
2007-02-13 01:22:17 +00:00
switch_ivr_transfer_variable ( session , nsession , SOFIA_SIP_HEADER_PREFIX_T ) ;
2007-02-21 21:46:32 +00:00
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
2007-03-29 22:31:56 +00:00
*/
2007-02-21 21:46:32 +00:00
private_object_t * ctech_pvt ;
ctech_pvt = switch_core_session_get_private ( session ) ;
assert ( ctech_pvt ! = NULL ) ;
tech_pvt - > bte = ctech_pvt - > te ;
2007-03-07 18:34:22 +00:00
tech_pvt - > bcng_pt = ctech_pvt - > cng_pt ;
2007-02-21 21:46:32 +00:00
}
2006-10-05 14:24:25 +00:00
}
2007-03-29 22:31:56 +00:00
done :
2007-02-09 20:03:07 +00:00
return cause ;
2006-08-25 23:55:59 +00:00
}
2007-03-29 22:31:56 +00:00
static uint8_t negotiate_sdp ( switch_core_session_t * session , sdp_session_t * sdp )
2006-08-25 23:55:59 +00:00
{
uint8_t match = 0 ;
2007-03-07 20:06:15 +00:00
switch_payload_t te = 0 , cng_pt = 0 ;
2006-08-25 23:55:59 +00:00
private_object_t * tech_pvt ;
sdp_media_t * m ;
2006-10-24 21:31:39 +00:00
sdp_attribute_t * a ;
2006-10-31 21:38:06 +00:00
switch_channel_t * channel ;
2007-03-29 22:31:56 +00:00
int ptime = 0 , dptime = 0 ;
2006-08-25 23:55:59 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
2007-02-21 21:46:32 +00:00
assert ( tech_pvt ! = NULL ) ;
2006-10-31 21:38:06 +00:00
channel = switch_core_session_get_channel ( session ) ;
2007-03-29 22:31:56 +00:00
2006-10-12 20:37:08 +00:00
if ( ( tech_pvt - > origin = switch_core_session_strdup ( session , ( char * ) sdp - > sdp_origin - > o_username ) ) ) {
if ( strstr ( tech_pvt - > origin , " CiscoSystemsSIP-GW-UserAgent " ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_BUGGY_2833 ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Activate Buggy RFC2833 Mode! \n " ) ;
}
}
2006-10-24 21:31:39 +00:00
for ( a = sdp - > sdp_attributes ; a ; a = a - > a_next ) {
if ( ! strcasecmp ( a - > a_name , " sendonly " ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_SIP_HOLD ) ;
} else if ( ! strcasecmp ( a - > a_name , " sendrecv " ) ) {
switch_clear_flag_locked ( tech_pvt , TFLAG_SIP_HOLD ) ;
2007-01-25 17:26:23 +00:00
} else if ( ! strcasecmp ( a - > a_name , " ptime " ) ) {
2007-03-29 22:31:56 +00:00
dptime = atoi ( a - > a_value ) ;
2006-10-24 21:31:39 +00:00
}
}
2007-03-29 22:31:56 +00:00
for ( m = sdp - > sdp_media ; m ; m = m - > m_next ) {
sdp_connection_t * connection ;
2007-02-04 23:04:16 +00:00
2007-03-29 22:31:56 +00:00
ptime = dptime ;
for ( a = m - > m_attributes ; a ; a = a - > a_next ) {
if ( ! strcasecmp ( a - > a_name , " ptime " ) & & a - > a_value ) {
ptime = atoi ( a - > a_value ) ;
}
}
2007-01-25 17:26:23 +00:00
2006-08-25 23:55:59 +00:00
if ( m - > m_type = = sdp_media_audio ) {
sdp_rtpmap_t * map ;
2007-02-25 21:37:02 +00:00
connection = sdp - > sdp_connection ;
if ( m - > m_connections ) {
connection = m - > m_connections ;
}
if ( ! connection ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot find a c= line in the sdp at media or session level! \n " ) ;
2007-02-25 21:37:02 +00:00
match = 0 ;
break ;
}
2006-08-25 23:55:59 +00:00
for ( map = m - > m_rtpmaps ; map ; map = map - > rm_next ) {
2007-01-29 16:44:44 +00:00
int32_t i ;
2007-03-29 22:31:56 +00:00
const switch_codec_implementation_t * mimp = NULL , * near_match = NULL ;
const char * rm_encoding ;
2007-01-26 15:42:38 +00:00
2007-03-28 15:15:01 +00:00
if ( ! ( rm_encoding = map - > rm_encoding ) ) {
rm_encoding = " " ;
}
2007-03-29 22:31:56 +00:00
2007-03-28 15:15:01 +00:00
if ( ! te & & ! strcasecmp ( rm_encoding , " telephone-event " ) ) {
2007-03-29 22:31:56 +00:00
te = tech_pvt - > te = ( switch_payload_t ) map - > rm_pt ;
2007-03-07 20:06:15 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Set 2833 dtmf payload to %u \n " , te ) ;
2007-03-09 01:15:54 +00:00
if ( tech_pvt - > rtp_session ) {
switch_rtp_set_telephony_event ( tech_pvt - > rtp_session , tech_pvt - > te ) ;
}
2007-02-25 21:00:26 +00:00
}
2007-03-28 15:15:01 +00:00
if ( ! cng_pt & & ! strcasecmp ( rm_encoding , " CN " ) ) {
2007-03-29 22:31:56 +00:00
cng_pt = tech_pvt - > cng_pt = ( switch_payload_t ) map - > rm_pt ;
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Set comfort noise payload to %u \n " , cng_pt ) ;
2007-03-07 23:48:02 +00:00
if ( tech_pvt - > rtp_session ) {
switch_rtp_set_cng_pt ( tech_pvt - > rtp_session , tech_pvt - > cng_pt ) ;
switch_rtp_set_flag ( tech_pvt - > rtp_session , SWITCH_RTP_FLAG_AUTO_CNG ) ;
}
2007-03-07 20:06:15 +00:00
}
2007-03-29 22:31:56 +00:00
2007-02-25 21:00:26 +00:00
if ( match ) {
2007-03-07 20:06:15 +00:00
if ( te & & cng_pt ) {
2007-02-25 21:00:26 +00:00
break ;
}
continue ;
2006-08-25 23:55:59 +00:00
}
2007-02-14 22:14:32 +00:00
2006-08-25 23:55:59 +00:00
for ( i = 0 ; i < tech_pvt - > num_codecs ; i + + ) {
const switch_codec_implementation_t * imp = tech_pvt - > codecs [ i ] ;
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Codec Compare [%s:%d]/[%s:%d] \n " ,
2007-03-28 15:15:01 +00:00
rm_encoding , map - > rm_pt , imp - > iananame , imp - > ianacode ) ;
2006-10-09 02:24:43 +00:00
if ( map - > rm_pt < 96 ) {
2006-08-25 23:55:59 +00:00
match = ( map - > rm_pt = = imp - > ianacode ) ? 1 : 0 ;
} else {
2007-03-28 15:15:01 +00:00
match = strcasecmp ( rm_encoding , imp - > iananame ) ? 0 : 1 ;
2006-08-25 23:55:59 +00:00
}
2006-10-31 21:38:06 +00:00
2006-08-25 23:55:59 +00:00
if ( match & & ( map - > rm_rate = = imp - > samples_per_second ) ) {
2007-03-29 22:31:56 +00:00
if ( ptime & & ptime * 1000 ! = imp - > microseconds_per_frame ) {
near_match = imp ;
match = 0 ;
continue ;
}
mimp = imp ;
2006-08-25 23:55:59 +00:00
break ;
} else {
match = 0 ;
}
2007-03-29 22:31:56 +00:00
}
if ( ! match & & near_match ) {
const switch_codec_implementation_t * search [ 1 ] ;
char * prefs [ 1 ] ;
char tmp [ 80 ] ;
int num ;
2007-03-30 00:13:31 +00:00
snprintf ( tmp , sizeof ( tmp ) , " %s@%uk@%ui " , near_match - > iananame , near_match - > samples_per_second , ptime ) ;
2007-03-29 22:31:56 +00:00
prefs [ 0 ] = tmp ;
num = switch_loadable_module_get_codecs_sorted ( search , 1 , prefs , 1 ) ;
if ( num ) {
mimp = search [ 0 ] ;
} else {
mimp = near_match ;
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Substituting codec %s@%ums \n " ,
mimp - > iananame , mimp - > microseconds_per_frame / 1000 ) ;
match = 1 ;
}
if ( mimp ) {
if ( ( tech_pvt - > rm_encoding = switch_core_session_strdup ( session , ( char * ) rm_encoding ) ) ) {
char tmp [ 50 ] ;
tech_pvt - > pt = ( switch_payload_t ) map - > rm_pt ;
tech_pvt - > rm_rate = map - > rm_rate ;
tech_pvt - > codec_ms = mimp - > microseconds_per_frame / 1000 ;
2007-03-30 00:13:31 +00:00
tech_pvt - > remote_sdp_audio_ip = switch_core_session_strdup ( session , ( char * ) connection - > c_address ) ;
2007-03-29 22:31:56 +00:00
tech_pvt - > rm_fmtp = switch_core_session_strdup ( session , ( char * ) map - > rm_fmtp ) ;
tech_pvt - > remote_sdp_audio_port = ( switch_port_t ) m - > m_port ;
tech_pvt - > agreed_pt = ( switch_payload_t ) map - > rm_pt ;
snprintf ( tmp , sizeof ( tmp ) , " %d " , tech_pvt - > remote_sdp_audio_port ) ;
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel , SWITCH_REMOTE_MEDIA_IP_VARIABLE , tech_pvt - > remote_sdp_audio_ip ) ;
2007-03-29 22:31:56 +00:00
switch_channel_set_variable ( channel , SWITCH_REMOTE_MEDIA_PORT_VARIABLE , tmp ) ;
} else {
match = 0 ;
}
}
2006-08-25 23:55:59 +00:00
if ( match ) {
2006-10-24 21:31:39 +00:00
if ( tech_set_codec ( tech_pvt , 1 ) ! = SWITCH_STATUS_SUCCESS ) {
2006-08-29 21:07:24 +00:00
match = 0 ;
}
2006-08-25 23:55:59 +00:00
}
}
}
}
return match ;
}
2006-10-25 03:45:20 +00:00
// map sip responses to QSIG cause codes ala RFC4497 section 8.4.4
2007-03-29 22:31:56 +00:00
static switch_call_cause_t sip_cause_to_freeswitch ( int status )
{
2006-09-12 22:24:39 +00:00
switch ( status ) {
2006-10-25 04:28:49 +00:00
case 200 :
return SWITCH_CAUSE_NORMAL_CLEARING ;
case 401 :
2007-03-29 22:31:56 +00:00
case 402 :
2006-10-25 04:28:49 +00:00
case 403 :
case 407 :
case 603 :
return SWITCH_CAUSE_CALL_REJECTED ;
case 404 :
case 485 :
2007-03-29 22:31:56 +00:00
case 604 :
2007-01-26 20:39:45 +00:00
return SWITCH_CAUSE_NO_ROUTE_DESTINATION ;
2007-03-29 22:31:56 +00:00
case 408 :
2006-10-25 04:28:49 +00:00
case 504 :
return SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE ;
2007-03-29 22:31:56 +00:00
case 410 :
2006-10-25 04:28:49 +00:00
return SWITCH_CAUSE_NUMBER_CHANGED ;
2007-03-29 22:31:56 +00:00
case 413 :
2006-10-25 04:28:49 +00:00
case 414 :
case 416 :
case 420 :
case 421 :
case 423 :
case 505 :
case 513 :
return SWITCH_CAUSE_INTERWORKING ;
case 480 :
return SWITCH_CAUSE_NO_USER_RESPONSE ;
case 400 :
case 481 :
case 500 :
case 503 :
return SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE ;
case 486 :
case 600 :
return SWITCH_CAUSE_USER_BUSY ;
case 484 :
return SWITCH_CAUSE_INVALID_NUMBER_FORMAT ;
case 488 :
case 606 :
return SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL ;
case 502 :
return SWITCH_CAUSE_NETWORK_OUT_OF_ORDER ;
case 405 :
return SWITCH_CAUSE_SERVICE_UNAVAILABLE ;
case 406 :
case 415 :
case 501 :
return SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED ;
case 482 :
case 483 :
return SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR ;
case 487 :
return SWITCH_CAUSE_ORIGINATOR_CANCEL ;
2007-03-29 22:31:56 +00:00
default :
2006-10-25 04:28:49 +00:00
return SWITCH_CAUSE_NORMAL_UNSPECIFIED ;
2006-09-12 22:24:39 +00:00
}
}
2006-10-18 22:57:35 +00:00
static void set_hash_key ( char * hash_key , int32_t len , sip_t const * sip )
{
2007-03-30 00:13:31 +00:00
snprintf ( hash_key , len , " %s%s%s " , ( char * ) sip - > sip_from - > a_url - > url_user , ( char * ) sip - > sip_from - > a_url - > url_host , ( char * ) sip - > sip_to - > a_url - > url_user ) ;
2006-10-18 22:57:35 +00:00
#if 0
/* nicer one we cant use in both directions >=0 */
snprintf ( hash_key , len , " %s%s%s%s%s%s " ,
( char * ) sip - > sip_to - > a_url - > url_user ,
( char * ) sip - > sip_to - > a_url - > url_host ,
( char * ) sip - > sip_to - > a_url - > url_params ,
2007-03-30 00:13:31 +00:00
( char * ) sip - > sip_from - > a_url - > url_user , ( char * ) sip - > sip_from - > a_url - > url_host , ( char * ) sip - > sip_from - > a_url - > url_params ) ;
2006-10-18 22:57:35 +00:00
# endif
}
2007-03-29 22:31:56 +00:00
static void set_chat_hash ( private_object_t * tech_pvt , sip_t const * sip )
2006-10-18 22:57:35 +00:00
{
char hash_key [ 256 ] = " " ;
char buf [ 512 ] ;
2007-03-30 00:13:31 +00:00
if ( tech_pvt - > hash_key | | ! sip | | ! sip - > sip_from | | ! sip - > sip_from - > a_url | | ! sip - > sip_from - > a_url - > url_user | | ! sip - > sip_from - > a_url - > url_host ) {
2006-10-18 22:57:35 +00:00
return ;
}
2007-03-30 00:13:31 +00:00
if ( find_reg_url ( tech_pvt - > profile , sip - > sip_from - > a_url - > url_user , sip - > sip_from - > a_url - > url_host , buf , sizeof ( buf ) ) ) {
2007-03-29 22:31:56 +00:00
tech_pvt - > chat_from = sip_header_as_string ( tech_pvt - > home , ( const sip_header_t * ) sip - > sip_to ) ;
2006-10-18 22:57:35 +00:00
tech_pvt - > chat_to = switch_core_session_strdup ( tech_pvt - > session , buf ) ;
set_hash_key ( hash_key , sizeof ( hash_key ) , sip ) ;
} else {
return ;
}
tech_pvt - > hash_key = switch_core_session_strdup ( tech_pvt - > session , hash_key ) ;
switch_core_hash_insert ( tech_pvt - > profile - > chat_hash , tech_pvt - > hash_key , tech_pvt ) ;
}
2006-10-12 00:59:09 +00:00
static void sip_i_message ( int status ,
2007-03-29 22:31:56 +00:00
char const * phrase ,
2007-03-30 00:13:31 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] )
2006-10-12 00:59:09 +00:00
{
if ( sip ) {
sip_from_t const * from = sip - > sip_from ;
char * from_user = NULL ;
char * from_host = NULL ;
sip_to_t const * to = sip - > sip_to ;
char * to_user = NULL ;
char * to_host = NULL ;
sip_subject_t const * sip_subject = sip - > sip_subject ;
sip_payload_t * payload = sip - > sip_payload ;
const char * subject = " n/a " ;
2006-10-18 22:57:35 +00:00
char * msg = NULL ;
2006-10-12 00:59:09 +00:00
2006-10-21 01:20:46 +00:00
if ( sip - > sip_content_type ) {
2007-03-29 22:31:56 +00:00
if ( strstr ( ( char * ) sip - > sip_content_type - > c_subtype , " composing " ) ) {
2006-10-21 01:20:46 +00:00
return ;
}
2006-10-15 05:10:34 +00:00
}
2006-10-12 00:59:09 +00:00
if ( from ) {
from_user = ( char * ) from - > a_url - > url_user ;
from_host = ( char * ) from - > a_url - > url_host ;
}
if ( to ) {
to_user = ( char * ) to - > a_url - > url_user ;
to_host = ( char * ) to - > a_url - > url_host ;
}
2007-03-29 22:31:56 +00:00
2006-10-20 22:11:26 +00:00
if ( ! to_user ) {
return ;
}
2006-10-12 00:59:09 +00:00
if ( payload ) {
msg = payload - > pl_data ;
}
if ( sip_subject ) {
subject = sip_subject - > g_value ;
}
2007-03-29 22:31:56 +00:00
if ( nh ) {
2006-10-18 22:57:35 +00:00
char hash_key [ 512 ] ;
private_object_t * tech_pvt ;
switch_channel_t * channel ;
switch_event_t * event ;
char * to_addr ;
char * from_addr ;
char * p ;
2006-10-19 07:13:34 +00:00
char * full_from ;
2006-10-20 22:11:26 +00:00
char proto [ 512 ] = SOFIA_CHAT_PROTO ;
2006-10-12 00:59:09 +00:00
2007-03-29 22:31:56 +00:00
full_from = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_from ) ;
if ( ( p = strchr ( to_user , ' + ' ) ) ) {
2006-10-19 07:13:34 +00:00
switch_copy_string ( proto , to_user , sizeof ( proto ) ) ;
p = strchr ( proto , ' + ' ) ;
* p + + = ' \0 ' ;
2007-03-29 22:31:56 +00:00
2006-10-19 07:13:34 +00:00
if ( ( to_addr = strdup ( p ) ) ) {
2007-03-29 22:31:56 +00:00
if ( ( p = strchr ( to_addr , ' + ' ) ) ) {
2006-10-20 22:11:26 +00:00
* p = ' @ ' ;
}
2006-10-18 22:57:35 +00:00
}
2007-03-29 22:31:56 +00:00
2006-10-18 22:57:35 +00:00
} else {
2006-10-19 16:33:54 +00:00
to_addr = switch_mprintf ( " %s@%s " , to_user , to_host ) ;
2006-10-18 22:57:35 +00:00
}
2006-10-12 00:59:09 +00:00
2006-10-20 22:11:26 +00:00
from_addr = switch_mprintf ( " %s@%s " , from_user , from_host ) ;
2006-10-18 22:57:35 +00:00
set_hash_key ( hash_key , sizeof ( hash_key ) , sip ) ;
if ( ( tech_pvt = ( private_object_t * ) switch_core_hash_find ( profile - > chat_hash , hash_key ) ) ) {
channel = switch_core_session_get_channel ( tech_pvt - > session ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_MESSAGE ) = = SWITCH_STATUS_SUCCESS ) {
2006-10-20 22:11:26 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
2006-10-18 22:57:35 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " login " , " %s " , profile - > url ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s " , tech_pvt - > hash_key ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " to " , " %s " , to_addr ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " subject " , " SIMPLE MESSAGE " ) ;
if ( msg ) {
2007-02-14 03:45:10 +00:00
switch_event_add_body ( event , " %s " , msg ) ;
2006-10-18 22:57:35 +00:00
}
if ( switch_core_session_queue_event ( tech_pvt - > session , & event ) ! = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " delivery-failure " , " true " ) ;
switch_event_fire ( & event ) ;
}
}
} else {
2006-10-19 07:13:34 +00:00
switch_chat_interface_t * ci ;
2007-03-29 22:31:56 +00:00
2006-10-19 07:13:34 +00:00
if ( ( ci = switch_loadable_module_get_chat_interface ( proto ) ) ) {
2006-10-20 22:11:26 +00:00
ci - > chat_send ( SOFIA_CHAT_PROTO , from_addr , to_addr , " " , msg , full_from ) ;
2006-10-19 07:13:34 +00:00
} else {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Chat Interface [%s]! \n " , proto ? proto : " (none) " ) ;
2006-10-18 22:57:35 +00:00
}
2007-03-29 22:31:56 +00:00
2006-10-12 00:59:09 +00:00
}
2006-10-18 22:57:35 +00:00
switch_safe_free ( to_addr ) ;
switch_safe_free ( from_addr ) ;
2006-10-19 07:13:34 +00:00
if ( full_from ) {
su_free ( profile - > home , full_from ) ;
}
2006-10-18 22:57:35 +00:00
}
2006-10-12 00:59:09 +00:00
}
}
2007-03-29 22:31:56 +00:00
static void pass_sdp ( private_object_t * tech_pvt , char * sdp )
2006-10-31 21:38:06 +00:00
{
char * val ;
2006-11-10 08:13:01 +00:00
switch_channel_t * channel ;
2006-10-31 21:38:06 +00:00
switch_core_session_t * other_session ;
switch_channel_t * other_channel ;
2007-03-29 22:31:56 +00:00
2006-11-10 08:13:01 +00:00
channel = switch_core_session_get_channel ( tech_pvt - > session ) ;
assert ( channel ! = NULL ) ;
2007-03-29 22:31:56 +00:00
if ( ( val = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) )
& & ( other_session = switch_core_session_locate ( val ) ) ) {
2006-10-31 21:38:06 +00:00
other_channel = switch_core_session_get_channel ( other_session ) ;
assert ( other_channel ! = NULL ) ;
2007-03-29 15:21:42 +00:00
switch_channel_set_variable ( other_channel , SWITCH_B_SDP_VARIABLE , sdp ) ;
2006-11-27 21:52:38 +00:00
2007-03-29 22:31:56 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_CHANGE_MEDIA ) & & ( switch_channel_test_flag ( other_channel , CF_OUTBOUND ) & &
//switch_channel_test_flag(other_channel, CF_NOMEDIA) &&
switch_channel_test_flag ( channel , CF_OUTBOUND ) & &
switch_channel_test_flag ( channel , CF_NOMEDIA ) ) ) {
2006-11-09 05:13:59 +00:00
switch_ivr_nomedia ( val , SMF_FORCE ) ;
2006-11-10 08:13:01 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_CHANGE_MEDIA ) ;
2006-10-31 21:38:06 +00:00
}
2007-03-29 22:31:56 +00:00
2006-10-31 21:38:06 +00:00
switch_core_session_rwunlock ( other_session ) ;
}
}
2006-08-25 23:55:59 +00:00
static void sip_i_state ( int status ,
2007-03-29 22:31:56 +00:00
char const * phrase ,
2007-03-30 00:13:31 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] )
2006-08-25 23:55:59 +00:00
{
2007-01-23 22:04:05 +00:00
const char * l_sdp = NULL , * r_sdp = NULL ;
2006-08-25 23:55:59 +00:00
int offer_recv = 0 , answer_recv = 0 , offer_sent = 0 , answer_sent = 0 ;
int ss_state = nua_callstate_init ;
switch_channel_t * channel = NULL ;
private_object_t * tech_pvt = NULL ;
2006-12-28 19:38:35 +00:00
switch_core_session_t * session = NULL ;
2006-10-09 19:30:54 +00:00
const char * replaces_str = NULL ;
2006-10-09 02:24:43 +00:00
char * uuid ;
switch_core_session_t * other_session = NULL ;
switch_channel_t * other_channel = NULL ;
2006-10-25 04:28:49 +00:00
char st [ 80 ] = " " ;
2006-10-05 14:45:56 +00:00
2006-12-28 19:38:35 +00:00
2007-03-29 22:31:56 +00:00
if ( sofia_private ) {
if ( ! switch_strlen_zero ( sofia_private - > uuid ) ) {
if ( ! ( session = switch_core_session_locate ( sofia_private - > uuid ) ) ) {
/* too late */
return ;
}
}
}
2006-12-28 19:38:35 +00:00
2007-03-29 22:31:56 +00:00
tl_gets ( tags ,
2006-08-25 23:55:59 +00:00
NUTAG_CALLSTATE_REF ( ss_state ) ,
NUTAG_OFFER_RECV_REF ( offer_recv ) ,
NUTAG_ANSWER_RECV_REF ( answer_recv ) ,
NUTAG_OFFER_SENT_REF ( offer_sent ) ,
NUTAG_ANSWER_SENT_REF ( answer_sent ) ,
2007-03-30 00:13:31 +00:00
SIPTAG_REPLACES_STR_REF ( replaces_str ) , SOATAG_LOCAL_SDP_STR_REF ( l_sdp ) , SOATAG_REMOTE_SDP_STR_REF ( r_sdp ) , TAG_END ( ) ) ;
2006-08-25 23:55:59 +00:00
if ( session ) {
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-03-29 22:31:56 +00:00
assert ( tech_pvt - > nh ! = NULL ) ;
2007-01-26 21:12:19 +00:00
2006-12-29 00:57:08 +00:00
if ( switch_channel_test_flag ( channel , CF_NOMEDIA ) ) {
2007-03-29 22:31:56 +00:00
switch_set_flag ( tech_pvt , TFLAG_NOMEDIA ) ;
}
2006-10-18 22:57:35 +00:00
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Channel %s entering state [%s] \n " ,
switch_channel_get_name ( channel ) , nua_callstate_name ( ss_state ) ) ;
2006-08-25 23:55:59 +00:00
2006-09-14 23:05:27 +00:00
if ( r_sdp ) {
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Remote SDP: \n %s \n " , r_sdp ) ;
2007-02-17 00:56:16 +00:00
tech_pvt - > remote_sdp_str = switch_core_session_strdup ( session , r_sdp ) ;
switch_channel_set_variable ( channel , SWITCH_R_SDP_VARIABLE , r_sdp ) ;
2007-03-29 22:31:56 +00:00
pass_sdp ( tech_pvt , ( char * ) r_sdp ) ;
2006-10-18 22:57:35 +00:00
2006-09-14 23:05:27 +00:00
}
2006-08-25 23:55:59 +00:00
}
2006-10-31 21:38:06 +00:00
if ( status = = 988 ) {
2006-12-28 19:38:35 +00:00
goto done ;
2006-10-31 21:38:06 +00:00
}
2006-09-14 23:05:27 +00:00
2007-03-29 22:31:56 +00:00
switch ( ( enum nua_callstate ) ss_state ) {
2006-08-25 23:55:59 +00:00
case nua_callstate_init :
break ;
case nua_callstate_authenticating :
break ;
case nua_callstate_calling :
break ;
case nua_callstate_proceeding :
2006-09-15 21:43:18 +00:00
if ( channel ) {
2007-02-13 14:58:06 +00:00
if ( status = = 180 ) {
2007-02-13 02:32:10 +00:00
switch_channel_mark_ring_ready ( channel ) ;
2007-02-13 14:58:06 +00:00
if ( ! switch_channel_test_flag ( channel , CF_GEN_RINGBACK ) ) {
if ( switch_test_flag ( tech_pvt , TFLAG_NOMEDIA ) ) {
2007-03-29 22:31:56 +00:00
if ( ( uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) )
& & ( other_session = switch_core_session_locate ( uuid ) ) ) {
2007-02-13 14:58:06 +00:00
switch_core_session_message_t msg ;
msg . message_id = SWITCH_MESSAGE_INDICATE_RINGING ;
msg . from = __FILE__ ;
switch_core_session_receive_message ( other_session , & msg ) ;
switch_core_session_rwunlock ( other_session ) ;
}
2007-03-29 22:31:56 +00:00
2007-02-13 14:58:06 +00:00
} else {
2007-02-13 15:47:15 +00:00
switch_core_session_queue_indication ( session , SWITCH_MESSAGE_INDICATE_RINGING ) ;
2006-10-12 00:59:09 +00:00
}
}
}
2007-02-10 19:34:03 +00:00
2006-09-15 21:43:18 +00:00
if ( r_sdp ) {
2006-10-06 22:39:49 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_NOMEDIA ) ) {
2006-10-08 15:51:10 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_EARLY_MEDIA ) ;
2007-03-29 22:31:56 +00:00
switch_channel_mark_pre_answered ( channel ) ;
2007-03-30 00:13:31 +00:00
if ( ! switch_channel_test_flag ( channel , CF_GEN_RINGBACK ) & & ( uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) )
2007-03-29 22:31:56 +00:00
& & ( other_session = switch_core_session_locate ( uuid ) ) ) {
2006-10-09 02:24:43 +00:00
other_channel = switch_core_session_get_channel ( other_session ) ;
2007-02-10 19:34:03 +00:00
if ( ! switch_channel_get_variable ( other_channel , SWITCH_B_SDP_VARIABLE ) ) {
2007-02-17 00:56:16 +00:00
switch_channel_set_variable ( other_channel , SWITCH_B_SDP_VARIABLE , r_sdp ) ;
2007-02-10 19:34:03 +00:00
}
2007-03-29 22:31:56 +00:00
2006-10-09 02:24:43 +00:00
switch_channel_pre_answer ( other_channel ) ;
switch_core_session_rwunlock ( other_session ) ;
}
2007-03-29 22:31:56 +00:00
goto done ;
2007-02-10 19:34:03 +00:00
} else {
if ( switch_test_flag ( tech_pvt , TFLAG_LATE_NEGOTIATION ) ) {
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " DELAYED NEGOTIATION " ) ;
2007-02-10 19:34:03 +00:00
} else {
2007-03-29 22:31:56 +00:00
if ( tech_media ( tech_pvt , ( char * ) r_sdp ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " CODEC NEGOTIATION ERROR " ) ;
2007-02-10 19:34:03 +00:00
nua_respond ( nh , SIP_488_NOT_ACCEPTABLE , TAG_END ( ) ) ;
}
}
goto done ;
2007-03-29 22:31:56 +00:00
}
2006-08-25 23:55:59 +00:00
}
}
break ;
case nua_callstate_completing :
nua_ack ( nh , TAG_END ( ) ) ;
break ;
2007-03-29 22:31:56 +00:00
case nua_callstate_received :
2007-03-15 18:46:16 +00:00
2006-11-22 17:48:53 +00:00
if ( session & & switch_core_session_running ( session ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Re-Entering Call State Received! \n " ) ;
2007-03-29 22:31:56 +00:00
goto done ;
2006-11-22 17:48:53 +00:00
}
2006-09-15 21:43:18 +00:00
if ( channel ) {
if ( r_sdp ) {
2006-10-06 22:39:49 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_NOMEDIA ) ) {
2007-02-28 15:48:17 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " RECEIVED_NOMEDIA " ) ;
2006-10-06 22:39:49 +00:00
switch_channel_set_state ( channel , CS_INIT ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_READY ) ;
switch_core_session_thread_launch ( session ) ;
2007-03-29 22:31:56 +00:00
goto done ;
2006-10-06 22:39:49 +00:00
} else {
2007-03-29 22:31:56 +00:00
sdp_parser_t * parser = sdp_parse ( tech_pvt - > home , r_sdp , ( int ) strlen ( r_sdp ) , 0 ) ;
2006-10-06 22:39:49 +00:00
sdp_session_t * sdp ;
uint8_t match = 0 ;
2007-03-29 22:31:56 +00:00
2006-10-06 22:39:49 +00:00
if ( tech_pvt - > num_codecs ) {
if ( ( sdp = sdp_session ( parser ) ) ) {
match = negotiate_sdp ( session , sdp ) ;
}
2006-09-15 21:43:18 +00:00
}
2006-08-25 23:55:59 +00:00
2006-10-06 22:39:49 +00:00
if ( parser ) {
sdp_parser_free ( parser ) ;
}
2006-08-25 23:55:59 +00:00
2006-10-06 22:39:49 +00:00
if ( match ) {
nua_handle_t * bnh ;
sip_replaces_t * replaces ;
2007-02-28 15:48:17 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " RECEIVED " ) ;
2006-10-06 22:39:49 +00:00
switch_channel_set_state ( channel , CS_INIT ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_READY ) ;
2006-10-31 21:38:06 +00:00
2006-10-06 22:39:49 +00:00
switch_core_session_thread_launch ( session ) ;
2007-03-29 22:31:56 +00:00
if ( replaces_str & & ( replaces = sip_replaces_make ( tech_pvt - > home , replaces_str ) )
& & ( bnh = nua_handle_by_replaces ( nua , replaces ) ) ) {
2006-10-06 22:39:49 +00:00
sofia_private_t * b_private ;
2006-10-05 14:24:25 +00:00
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Processing Replaces Attended Transfer \n " ) ;
2006-10-06 22:39:49 +00:00
while ( switch_channel_get_state ( channel ) < CS_EXECUTE ) {
switch_yield ( 10000 ) ;
}
2006-10-05 14:24:25 +00:00
2006-10-07 18:54:29 +00:00
if ( ( b_private = nua_handle_magic ( bnh ) ) ) {
2007-03-09 20:37:30 +00:00
char * br_b = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ;
2006-12-28 19:38:35 +00:00
char * br_a = b_private - > uuid ;
2006-10-06 22:39:49 +00:00
if ( br_b ) {
switch_ivr_uuid_bridge ( br_a , br_b ) ;
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " ATTENDED_TRANSFER " ) ;
2006-10-06 22:39:49 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_ATTENDED_TRANSFER ) ;
} else {
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " ATTENDED_TRANSFER_ERROR " ) ;
2006-10-06 22:39:49 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
2006-10-05 14:24:25 +00:00
} else {
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " ATTENDED_TRANSFER_ERROR " ) ;
2006-10-05 14:24:25 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
2006-10-06 22:39:49 +00:00
nua_handle_unref ( bnh ) ;
2006-10-05 14:24:25 +00:00
}
2007-03-29 22:31:56 +00:00
goto done ;
2006-10-05 14:24:25 +00:00
}
2007-02-28 15:48:17 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " NO CODECS " ) ;
2007-03-29 22:31:56 +00:00
nua_respond ( nh , SIP_488_NOT_ACCEPTABLE , TAG_END ( ) ) ;
2006-10-06 22:39:49 +00:00
}
2007-03-15 18:46:16 +00:00
} else {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Invite with no SDP activating no-media-mode \n " ) ;
2007-03-20 16:03:09 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " RECEIVED_NOSDP " ) ;
2007-03-15 18:46:16 +00:00
2007-03-20 16:03:09 +00:00
switch_set_flag ( tech_pvt , TFLAG_LATE_NEGOTIATION ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_NOMEDIA ) ;
switch_channel_set_flag ( channel , CF_NOMEDIA ) ;
switch_channel_set_state ( channel , CS_INIT ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_READY ) ;
switch_core_session_thread_launch ( session ) ;
2007-03-15 18:46:16 +00:00
goto done ;
2006-08-25 23:55:59 +00:00
}
}
2006-09-15 21:43:18 +00:00
2007-03-29 22:31:56 +00:00
break ;
2006-08-25 23:55:59 +00:00
case nua_callstate_early :
break ;
case nua_callstate_completed :
2006-09-30 19:17:35 +00:00
if ( tech_pvt & & r_sdp ) {
2006-10-06 22:39:49 +00:00
if ( r_sdp ) {
if ( switch_test_flag ( tech_pvt , TFLAG_NOMEDIA ) ) {
2007-03-29 22:31:56 +00:00
goto done ;
2006-10-06 22:39:49 +00:00
} else {
2007-03-29 22:31:56 +00:00
sdp_parser_t * parser = sdp_parse ( tech_pvt - > home , r_sdp , ( int ) strlen ( r_sdp ) , 0 ) ;
2006-10-06 22:39:49 +00:00
sdp_session_t * sdp ;
uint8_t match = 0 ;
2006-10-03 04:08:30 +00:00
2006-10-06 22:39:49 +00:00
if ( tech_pvt - > num_codecs ) {
if ( ( sdp = sdp_session ( parser ) ) ) {
match = negotiate_sdp ( session , sdp ) ;
}
}
2006-10-24 21:31:39 +00:00
if ( match ) {
2007-01-15 16:59:42 +00:00
if ( tech_choose_port ( tech_pvt ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:31:56 +00:00
goto done ;
}
2006-10-31 21:38:06 +00:00
set_local_sdp ( tech_pvt , NULL , 0 , NULL , 0 ) ;
2006-10-24 21:31:39 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_REINVITE ) ;
activate_rtp ( tech_pvt ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Processing Reinvite \n " ) ;
if ( parser ) {
sdp_parser_free ( parser ) ;
}
2006-10-06 22:39:49 +00:00
}
2006-10-03 04:08:30 +00:00
}
}
2006-09-30 19:17:35 +00:00
}
2006-08-25 23:55:59 +00:00
break ;
case nua_callstate_ready :
2007-01-06 20:57:30 +00:00
if ( tech_pvt & & nh = = tech_pvt - > nh2 ) {
2006-10-06 22:39:49 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Cheater Reinvite! \n " ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_REINVITE ) ;
tech_pvt - > nh = tech_pvt - > nh2 ;
tech_pvt - > nh2 = NULL ;
2007-01-15 16:59:42 +00:00
if ( tech_choose_port ( tech_pvt ) = = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:31:56 +00:00
activate_rtp ( tech_pvt ) ;
}
2006-12-28 19:38:35 +00:00
goto done ;
2006-10-06 22:39:49 +00:00
}
2006-09-15 21:43:18 +00:00
if ( channel ) {
2007-02-10 19:34:03 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_EARLY_MEDIA ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_ANS ) ;
2007-03-29 22:31:56 +00:00
switch_channel_mark_answered ( channel ) ;
if ( ( uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) )
& & ( other_session = switch_core_session_locate ( uuid ) ) ) {
other_channel = switch_core_session_get_channel ( other_session ) ;
switch_channel_answer ( other_channel ) ;
switch_core_session_rwunlock ( other_session ) ;
}
2007-02-10 19:34:03 +00:00
goto done ;
}
if ( ! r_sdp ) {
r_sdp = ( const char * ) switch_channel_get_variable ( channel , SWITCH_R_SDP_VARIABLE ) ;
}
2006-08-26 21:13:56 +00:00
if ( r_sdp ) {
2006-10-06 22:39:49 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_NOMEDIA ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_ANS ) ;
2007-03-29 22:31:56 +00:00
switch_channel_mark_answered ( channel ) ;
if ( ( uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) )
& & ( other_session = switch_core_session_locate ( uuid ) ) ) {
2006-10-09 02:24:43 +00:00
other_channel = switch_core_session_get_channel ( other_session ) ;
2007-02-10 19:34:03 +00:00
if ( ! switch_channel_get_variable ( other_channel , SWITCH_B_SDP_VARIABLE ) ) {
2007-02-17 00:56:16 +00:00
switch_channel_set_variable ( other_channel , SWITCH_B_SDP_VARIABLE , r_sdp ) ;
2007-02-10 19:34:03 +00:00
}
2006-10-09 02:24:43 +00:00
switch_channel_answer ( other_channel ) ;
switch_core_session_rwunlock ( other_session ) ;
}
2006-12-28 19:38:35 +00:00
goto done ;
2006-10-06 22:39:49 +00:00
} else {
2007-03-29 22:31:56 +00:00
sdp_parser_t * parser = sdp_parse ( tech_pvt - > home , r_sdp , ( int ) strlen ( r_sdp ) , 0 ) ;
2006-10-06 22:39:49 +00:00
sdp_session_t * sdp ;
uint8_t match = 0 ;
2006-08-26 21:13:56 +00:00
2006-10-06 22:39:49 +00:00
if ( tech_pvt - > num_codecs ) {
if ( ( sdp = sdp_session ( parser ) ) ) {
match = negotiate_sdp ( session , sdp ) ;
}
2006-08-26 21:13:56 +00:00
}
2006-08-25 23:55:59 +00:00
2006-10-06 22:39:49 +00:00
if ( parser ) {
sdp_parser_free ( parser ) ;
}
2006-08-25 23:55:59 +00:00
2006-10-06 22:39:49 +00:00
if ( match ) {
switch_set_flag_locked ( tech_pvt , TFLAG_ANS ) ;
2007-01-15 16:59:42 +00:00
if ( tech_choose_port ( tech_pvt ) = = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:31:56 +00:00
activate_rtp ( tech_pvt ) ;
switch_channel_mark_answered ( channel ) ;
goto done ;
}
2006-10-06 22:39:49 +00:00
}
2007-03-29 22:31:56 +00:00
2007-02-28 15:48:17 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " NO CODECS " ) ;
2006-10-06 22:39:49 +00:00
nua_respond ( nh , SIP_488_NOT_ACCEPTABLE , TAG_END ( ) ) ;
2006-08-26 21:13:56 +00:00
}
2007-02-10 19:34:03 +00:00
}
2007-03-29 22:31:56 +00:00
2006-09-14 23:48:19 +00:00
}
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
break ;
case nua_callstate_terminating :
break ;
2007-03-29 22:31:56 +00:00
case nua_callstate_terminated :
2006-08-25 23:55:59 +00:00
if ( session ) {
2006-10-12 02:26:20 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_BYE ) ) {
2007-03-29 22:31:56 +00:00
2006-10-12 02:26:20 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_BYE ) ;
if ( switch_test_flag ( tech_pvt , TFLAG_NOHUP ) ) {
switch_clear_flag_locked ( tech_pvt , TFLAG_NOHUP ) ;
} else {
2006-10-25 04:28:49 +00:00
snprintf ( st , sizeof ( st ) , " %d " , status ) ;
switch_channel_set_variable ( channel , " sip_term_status " , st ) ;
2006-10-12 02:26:20 +00:00
terminate_session ( & session , sip_cause_to_freeswitch ( status ) , __LINE__ ) ;
}
2006-10-06 22:39:49 +00:00
}
2006-12-28 01:08:06 +00:00
2007-03-29 22:31:56 +00:00
if ( tech_pvt - > sofia_private ) {
free ( tech_pvt - > sofia_private ) ;
tech_pvt - > sofia_private = NULL ;
}
2006-10-26 20:02:57 +00:00
tech_pvt - > nh = NULL ;
2006-12-28 19:38:35 +00:00
} else if ( sofia_private ) {
2007-03-29 22:31:56 +00:00
free ( sofia_private ) ;
}
2006-12-28 19:38:35 +00:00
2006-10-26 20:02:57 +00:00
if ( nh ) {
2007-03-29 22:31:56 +00:00
nua_handle_bind ( nh , NULL ) ;
2006-10-26 20:02:57 +00:00
nua_handle_destroy ( nh ) ;
2006-08-25 23:55:59 +00:00
}
break ;
}
2007-03-29 22:31:56 +00:00
done :
2006-12-28 19:38:35 +00:00
2007-03-29 22:31:56 +00:00
if ( session ) {
switch_core_session_rwunlock ( session ) ;
}
2006-08-25 23:55:59 +00:00
}
2007-03-30 00:13:31 +00:00
static char * get_auth_data ( char * dbname , char * nonce , char * npassword , size_t len , switch_mutex_t * mutex )
2006-09-28 21:21:44 +00:00
{
switch_core_db_t * db ;
switch_core_db_stmt_t * stmt ;
2006-09-28 21:29:32 +00:00
char * sql = NULL , * ret = NULL ;
2006-09-28 21:21:44 +00:00
if ( mutex ) {
switch_mutex_lock ( mutex ) ;
}
2007-02-06 18:37:01 +00:00
if ( ! dbname ) {
goto end ;
}
2006-09-28 21:21:44 +00:00
if ( ! ( db = switch_core_db_open_file ( dbname ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB %s \n " , dbname ) ;
goto end ;
}
2006-10-19 16:33:54 +00:00
sql = switch_mprintf ( " select passwd from sip_authentication where nonce='%q' " , nonce ) ;
2006-10-20 22:11:26 +00:00
if ( switch_core_db_prepare ( db , sql , - 1 , & stmt , 0 ) ) {
2006-09-28 21:21:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Statement Error! \n " ) ;
goto fail ;
} else {
int running = 1 ;
int colcount ;
while ( running < 5000 ) {
int result = switch_core_db_step ( stmt ) ;
2007-03-09 20:44:13 +00:00
if ( result = = SWITCH_CORE_DB_ROW ) {
2006-09-28 21:21:44 +00:00
if ( ( colcount = switch_core_db_column_count ( stmt ) ) ) {
2007-03-29 22:31:56 +00:00
switch_copy_string ( npassword , ( char * ) switch_core_db_column_text ( stmt , 0 ) , len ) ;
2006-09-28 21:21:44 +00:00
ret = npassword ;
}
break ;
2007-03-09 20:44:13 +00:00
} else if ( result = = SWITCH_CORE_DB_BUSY ) {
2006-09-28 21:21:44 +00:00
running + + ;
switch_yield ( 1000 ) ;
continue ;
}
break ;
}
2007-03-29 22:31:56 +00:00
2006-09-28 21:21:44 +00:00
switch_core_db_finalize ( stmt ) ;
}
2007-03-29 22:31:56 +00:00
fail :
2006-09-28 21:21:44 +00:00
switch_core_db_close ( db ) ;
2007-03-29 22:31:56 +00:00
end :
2006-09-28 21:21:44 +00:00
if ( mutex ) {
switch_mutex_unlock ( mutex ) ;
}
if ( sql ) {
2006-10-19 16:33:54 +00:00
switch_safe_free ( sql ) ;
2006-09-28 21:21:44 +00:00
}
2007-03-29 22:31:56 +00:00
2006-09-28 21:21:44 +00:00
return ret ;
}
2006-09-27 03:44:14 +00:00
2006-09-29 01:07:51 +00:00
typedef enum {
REG_REGISTER ,
REG_INVITE
} sofia_regtype_t ;
2007-03-30 00:13:31 +00:00
static uint8_t handle_register ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sip_t const * sip , sofia_regtype_t regtype , char * key , uint32_t keylen )
2006-09-27 03:44:14 +00:00
{
2007-03-05 06:04:37 +00:00
sip_from_t const * from = NULL ;
sip_expires_t const * expires = NULL ;
sip_authorization_t const * authorization = NULL ;
sip_contact_t const * contact = NULL ;
2006-10-22 04:37:19 +00:00
switch_xml_t domain , xml , user , param , xparams ;
2006-09-27 03:44:14 +00:00
char params [ 1024 ] = " " ;
char * sql ;
switch_event_t * s_event ;
2007-03-05 06:04:37 +00:00
const char * from_user = NULL ;
const char * from_host = NULL ;
2006-10-20 06:17:00 +00:00
char contact_str [ 1024 ] = " " ;
2006-09-27 03:44:14 +00:00
char buf [ 512 ] ;
2007-03-05 06:56:13 +00:00
const char * passwd = NULL ;
const char * a1_hash = NULL ;
2006-09-29 18:12:31 +00:00
uint8_t stale = 0 , ret = 0 , forbidden = 0 ;
auth_res_t auth_res ;
long exptime = 60 ;
2006-10-18 22:57:35 +00:00
switch_event_t * event ;
2007-02-14 19:15:20 +00:00
const char * rpid = " unknown " ;
2006-11-13 21:17:57 +00:00
const char * display = " \" user \" " ;
2006-09-29 18:12:31 +00:00
2007-03-05 06:04:37 +00:00
/* all callers must confirm that sip, sip->sip_request and sip->sip_contact are not NULL */
assert ( sip ! = NULL & & sip - > sip_contact ! = NULL & & sip - > sip_request ! = NULL ) ;
expires = sip - > sip_expires ;
authorization = sip - > sip_authorization ;
contact = sip - > sip_contact ;
from = sip - > sip_from ;
if ( from ) {
from_user = from - > a_url - > url_user ;
from_host = from - > a_url - > url_host ;
}
if ( ! from_user | | ! from_host ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can not do authorization without a complete from header \n " ) ;
2007-03-05 06:04:37 +00:00
nua_respond ( nh , SIP_500_INTERNAL_SERVER_ERROR , TAG_END ( ) ) ;
return 1 ;
}
if ( contact - > m_url ) {
const char * port = contact - > m_url - > url_port ;
2006-11-13 21:17:57 +00:00
display = contact - > m_display ;
if ( switch_strlen_zero ( display ) ) {
if ( from ) {
display = from - > a_display ;
if ( switch_strlen_zero ( display ) ) {
display = " \" user \" " ;
}
}
}
2007-03-29 22:31:56 +00:00
2006-10-18 22:57:35 +00:00
if ( ! port ) {
2007-03-19 21:09:53 +00:00
port = SOFIA_DEFAULT_PORT ;
2006-10-18 22:57:35 +00:00
}
2006-11-13 21:17:57 +00:00
2006-10-15 05:10:34 +00:00
if ( contact - > m_url - > url_params ) {
2007-03-29 22:31:56 +00:00
snprintf ( contact_str , sizeof ( contact_str ) , " %s <sip:%s@%s:%s;%s> " ,
2006-11-13 21:17:57 +00:00
display , contact - > m_url - > url_user , contact - > m_url - > url_host , port , contact - > m_url - > url_params ) ;
2006-10-15 05:10:34 +00:00
} else {
2007-03-30 00:13:31 +00:00
snprintf ( contact_str , sizeof ( contact_str ) , " %s <sip:%s@%s:%s> " , display , contact - > m_url - > url_user , contact - > m_url - > url_host , port ) ;
2006-10-15 05:10:34 +00:00
}
}
2007-03-29 22:31:56 +00:00
2006-09-29 18:12:31 +00:00
if ( expires ) {
exptime = expires - > ex_delta ;
2007-03-05 06:04:37 +00:00
} else if ( contact - > m_expires ) {
2006-09-29 18:12:31 +00:00
exptime = atol ( contact - > m_expires ) ;
2007-03-29 22:31:56 +00:00
}
2006-09-29 01:07:51 +00:00
if ( regtype = = REG_REGISTER ) {
authorization = sip - > sip_authorization ;
} else if ( regtype = = REG_INVITE ) {
authorization = sip - > sip_proxy_authorization ;
}
2006-09-27 03:44:14 +00:00
2006-09-29 18:12:31 +00:00
if ( ( profile - > pflags & PFLAG_BLIND_REG ) ) {
goto reg ;
}
2006-09-29 01:07:51 +00:00
2006-09-29 18:12:31 +00:00
if ( authorization ) {
2007-03-30 00:13:31 +00:00
if ( ( auth_res = parse_auth ( profile , authorization , sip - > sip_request - > rq_method_name , key , keylen ) ) = = AUTH_STALE ) {
2007-03-29 22:31:56 +00:00
stale = 1 ;
}
2006-09-29 18:12:31 +00:00
2006-12-13 20:10:00 +00:00
if ( auth_res ! = AUTH_OK & & ! stale ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " send %s for [%s@%s] \n " , forbidden ? " forbidden " : " challange " , from_user , from_host ) ;
2006-09-29 18:12:31 +00:00
if ( auth_res = = AUTH_FORBIDDEN ) {
2006-11-09 19:33:49 +00:00
nua_respond ( nh , SIP_403_FORBIDDEN , NUTAG_WITH_THIS ( nua ) , TAG_END ( ) ) ;
2006-09-29 01:07:51 +00:00
} else {
2006-11-09 19:33:49 +00:00
nua_respond ( nh , SIP_401_UNAUTHORIZED , NUTAG_WITH_THIS ( nua ) , TAG_END ( ) ) ;
2006-09-28 21:21:44 +00:00
}
2006-09-29 01:07:51 +00:00
return 1 ;
2006-09-28 21:21:44 +00:00
}
2007-03-29 22:31:56 +00:00
}
2006-09-28 21:21:44 +00:00
if ( ! authorization | | stale ) {
2007-03-29 22:31:56 +00:00
snprintf ( params , sizeof ( params ) , " from_user=%s&from_host=%s&contact=%s " , from_user , from_host , contact_str ) ;
2006-09-28 21:21:44 +00:00
2006-09-29 01:07:51 +00:00
if ( switch_xml_locate ( " directory " , " domain " , " name " , from_host , & xml , & domain , params ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " can't find domain for [%s@%s] \n " , from_user , from_host ) ;
2006-11-09 19:33:49 +00:00
nua_respond ( nh , SIP_401_UNAUTHORIZED , NUTAG_WITH_THIS ( nua ) , SIPTAG_CONTACT ( contact ) , TAG_END ( ) ) ;
2006-09-29 01:07:51 +00:00
return 1 ;
2006-09-28 21:21:44 +00:00
}
if ( ! ( user = switch_xml_find_child ( domain , " user " , " id " , from_user ) ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " can't find user [%s@%s] \n " , from_user , from_host ) ;
2006-11-09 19:33:49 +00:00
nua_respond ( nh , SIP_401_UNAUTHORIZED , NUTAG_WITH_THIS ( nua ) , SIPTAG_CONTACT ( contact ) , TAG_END ( ) ) ;
2006-09-28 21:21:44 +00:00
switch_xml_free ( xml ) ;
2006-09-29 01:07:51 +00:00
return 1 ;
2006-09-28 21:21:44 +00:00
}
2006-10-22 04:37:19 +00:00
2006-11-06 16:35:23 +00:00
if ( ! ( xparams = switch_xml_child ( user , " params " ) ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " can't find params for user [%s@%s] \n " , from_user , from_host ) ;
2006-11-09 19:33:49 +00:00
nua_respond ( nh , SIP_401_UNAUTHORIZED , NUTAG_WITH_THIS ( nua ) , SIPTAG_CONTACT ( contact ) , TAG_END ( ) ) ;
2006-10-22 04:37:19 +00:00
switch_xml_free ( xml ) ;
return 1 ;
}
2007-03-29 22:31:56 +00:00
2006-09-28 21:21:44 +00:00
2006-10-22 04:37:19 +00:00
for ( param = switch_xml_child ( xparams , " param " ) ; param ; param = param - > next ) {
2007-03-05 06:56:13 +00:00
const char * var = switch_xml_attr_soft ( param , " name " ) ;
const char * val = switch_xml_attr_soft ( param , " value " ) ;
2007-03-29 22:31:56 +00:00
2006-09-28 21:21:44 +00:00
if ( ! strcasecmp ( var , " password " ) ) {
passwd = val ;
}
2007-01-17 22:42:52 +00:00
if ( ! strcasecmp ( var , " a1-hash " ) ) {
2007-03-29 22:31:56 +00:00
a1_hash = val ;
2007-01-17 22:42:52 +00:00
}
2006-09-28 21:21:44 +00:00
}
2007-03-29 22:31:56 +00:00
2007-01-17 22:42:52 +00:00
if ( passwd | | a1_hash ) {
2006-09-28 21:21:44 +00:00
switch_uuid_t uuid ;
char uuid_str [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] ;
char * sql , * auth_str ;
su_md5_t ctx ;
char hexdigest [ 2 * SU_MD5_DIGEST_SIZE + 1 ] ;
char * input ;
2007-03-29 22:31:56 +00:00
if ( ! a1_hash ) {
input = switch_mprintf ( " %s:%s:%s " , from_user , from_host , passwd ) ;
su_md5_init ( & ctx ) ;
su_md5_strupdate ( & ctx , input ) ;
su_md5_hexdigest ( & ctx , hexdigest ) ;
su_md5_deinit ( & ctx ) ;
switch_safe_free ( input ) ;
switch_uuid_get ( & uuid ) ;
switch_uuid_format ( uuid_str , & uuid ) ;
a1_hash = hexdigest ;
}
2006-09-29 18:12:31 +00:00
2006-10-20 13:32:44 +00:00
sql = switch_mprintf ( " delete from sip_authentication where user='%q' and host='%q'; \n "
2007-03-29 22:31:56 +00:00
" insert into sip_authentication values('%q','%q','%q','%q', %ld) " ,
2007-03-30 00:13:31 +00:00
from_user , from_host , from_user , from_host , a1_hash , uuid_str , time ( NULL ) + profile - > nonce_ttl ) ;
auth_str = switch_mprintf ( " Digest realm= \" %q \" , nonce= \" %q \" ,%s algorithm=MD5, qop= \" auth \" " , from_host , uuid_str , stale ? " stale= \" true \" , " : " " ) ;
2006-09-27 03:44:14 +00:00
2006-09-29 01:07:51 +00:00
if ( regtype = = REG_REGISTER ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Requesting Registration from: [%s@%s] \n " , from_user , from_host ) ;
nua_respond ( nh , SIP_401_UNAUTHORIZED , NUTAG_WITH_THIS ( nua ) , SIPTAG_WWW_AUTHENTICATE_STR ( auth_str ) , TAG_END ( ) ) ;
2006-09-29 01:07:51 +00:00
} else if ( regtype = = REG_INVITE ) {
2007-03-30 00:13:31 +00:00
nua_respond ( nh , SIP_407_PROXY_AUTH_REQUIRED , NUTAG_WITH_THIS ( nua ) , SIPTAG_PROXY_AUTHENTICATE_STR ( auth_str ) , TAG_END ( ) ) ;
2006-09-29 01:07:51 +00:00
}
2006-09-28 21:21:44 +00:00
2006-09-30 00:00:07 +00:00
execute_sql ( profile - > dbname , sql , profile - > ireg_mutex ) ;
2006-10-19 16:33:54 +00:00
switch_safe_free ( sql ) ;
switch_safe_free ( auth_str ) ;
2006-09-29 01:07:51 +00:00
ret = 1 ;
} else {
ret = 0 ;
2006-09-28 21:21:44 +00:00
}
2007-03-29 22:31:56 +00:00
2006-09-28 21:21:44 +00:00
switch_xml_free ( xml ) ;
2006-09-29 01:07:51 +00:00
if ( ret ) {
return ret ;
}
2006-09-28 21:21:44 +00:00
}
2007-03-29 22:31:56 +00:00
reg :
2006-09-27 03:44:14 +00:00
2006-10-20 06:17:00 +00:00
if ( exptime ) {
if ( ! find_reg_url ( profile , from_user , from_host , buf , sizeof ( buf ) ) ) {
2007-03-29 22:31:56 +00:00
sql = switch_mprintf ( " insert into sip_registrations values ('%q','%q','%q','Registered', '%q', %ld) " ,
from_user , from_host , contact_str , rpid , ( long ) time ( NULL ) + ( long ) exptime * 2 ) ;
2006-09-29 01:07:51 +00:00
2006-10-20 06:17:00 +00:00
} else {
2007-03-29 22:31:56 +00:00
sql =
switch_mprintf
( " update sip_registrations set contact='%q', expires=%ld, rpid='%q' where user='%q' and host='%q' " ,
contact_str , ( long ) time ( NULL ) + ( long ) exptime * 2 , rpid , from_user , from_host ) ;
2006-10-20 06:17:00 +00:00
}
2006-09-29 01:07:51 +00:00
2006-10-20 06:17:00 +00:00
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_REGISTER ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " profile-name " , " %s " , profile - > name ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " from-user " , " %s " , from_user ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " from-host " , " %s " , from_host ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " contact " , " %s " , contact_str ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " rpid " , " %s " , rpid ) ;
2007-03-29 22:31:56 +00:00
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " expires " , " %ld " , ( long ) exptime ) ;
2006-10-20 06:17:00 +00:00
switch_event_fire ( & s_event ) ;
}
2006-09-27 04:34:19 +00:00
2006-10-20 06:17:00 +00:00
if ( sql ) {
execute_sql ( profile - > dbname , sql , profile - > ireg_mutex ) ;
switch_safe_free ( sql ) ;
sql = NULL ;
}
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
2007-03-30 00:13:31 +00:00
" Register: \n From: [%s@%s] \n Contact: [%s] \n Expires: [%ld] \n " , from_user , from_host , contact_str , ( long ) exptime ) ;
2006-09-27 03:44:14 +00:00
2006-10-18 22:57:35 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , " sip " ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " login " , " %s " , profile - > url ) ;
2006-10-20 06:17:00 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " rpid " , " %s " , rpid ) ;
2006-10-20 22:11:26 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , from_user , from_host ) ;
2007-03-29 22:31:56 +00:00
2006-10-18 22:57:35 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " status " , " Registered " ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " event_type " , " presence " ) ;
switch_event_fire ( & event ) ;
}
} else {
2006-10-20 06:17:00 +00:00
if ( ( sql = switch_mprintf ( " delete from sip_subscriptions where user='%q' and host='%q' " , from_user , from_host ) ) ) {
execute_sql ( profile - > dbname , sql , profile - > ireg_mutex ) ;
switch_safe_free ( sql ) ;
sql = NULL ;
}
2006-10-18 22:57:35 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_OUT ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , " sip " ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " login " , " %s " , profile - > url ) ;
2007-03-30 00:13:31 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s+%s@%s " , SOFIA_CHAT_PROTO , from_user , from_host ) ;
2007-03-29 22:31:56 +00:00
2006-10-18 22:57:35 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " status " , " unavailable " ) ;
2007-02-13 04:43:49 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " rpid " , " %s " , rpid ) ;
2006-10-18 22:57:35 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " event_type " , " presence " ) ;
switch_event_fire ( & event ) ;
}
}
2006-10-20 06:17:00 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_ROSTER ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , " sip " ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , from_user , from_host ) ;
switch_event_fire ( & event ) ;
}
2006-09-29 01:07:51 +00:00
if ( regtype = = REG_REGISTER ) {
2007-03-29 22:31:56 +00:00
nua_respond ( nh , SIP_200_OK , SIPTAG_CONTACT ( contact ) , NUTAG_WITH_THIS ( nua ) , TAG_END ( ) ) ;
2006-09-29 01:07:51 +00:00
return 1 ;
}
2006-09-28 21:21:44 +00:00
2006-09-29 01:07:51 +00:00
return 0 ;
}
2006-10-19 19:39:18 +00:00
static int sub_reg_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
sofia_profile_t * profile = ( sofia_profile_t * ) pArg ;
2006-10-20 22:11:26 +00:00
//char *proto = argv[0];
char * user = argv [ 1 ] ;
char * host = argv [ 2 ] ;
2006-10-19 19:39:18 +00:00
switch_event_t * event ;
2006-10-20 22:11:26 +00:00
char * status = NULL ;
2006-10-19 19:39:18 +00:00
if ( switch_strlen_zero ( status ) ) {
status = " Available " ;
}
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
2006-10-20 22:11:26 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
2006-10-19 19:39:18 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " login " , " %s " , profile - > url ) ;
2006-10-20 22:11:26 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , user , host ) ;
2006-10-20 06:17:00 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " status " , " %s " , status ) ;
2006-10-19 19:39:18 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " event_type " , " presence " ) ;
2006-10-20 06:17:00 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " event_subtype " , " probe " ) ;
2006-10-19 19:39:18 +00:00
switch_event_fire ( & event ) ;
}
return 0 ;
}
2006-10-20 22:11:26 +00:00
static int resub_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
sofia_profile_t * profile = ( sofia_profile_t * ) pArg ;
char * user = argv [ 0 ] ;
char * host = argv [ 1 ] ;
char * status = argv [ 2 ] ;
char * rpid = argv [ 3 ] ;
2006-10-22 04:37:19 +00:00
char * proto = argv [ 4 ] ;
2006-10-20 22:11:26 +00:00
switch_event_t * event ;
2006-10-22 04:37:19 +00:00
if ( switch_strlen_zero ( proto ) ) {
proto = NULL ;
}
2006-10-20 22:11:26 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
2007-02-13 04:43:49 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , " %s " , proto ? proto : SOFIA_CHAT_PROTO ) ;
2006-10-20 22:11:26 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " login " , " %s " , profile - > url ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , user , host ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " status " , " %s " , status ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " rpid " , " %s " , rpid ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " event_type " , " presence " ) ;
switch_event_fire ( & event ) ;
}
return 0 ;
}
2006-10-19 19:39:18 +00:00
static int sub_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
sofia_profile_t * profile = ( sofia_profile_t * ) pArg ;
char * pl ;
char * id , * note ;
uint32_t in = atoi ( argv [ 0 ] ) ;
2006-10-20 06:17:00 +00:00
char * status = argv [ 1 ] ;
char * rpid = argv [ 2 ] ;
char * proto = argv [ 3 ] ;
char * user = argv [ 4 ] ;
char * host = argv [ 5 ] ;
char * sub_to_user = argv [ 6 ] ;
char * sub_to_host = argv [ 7 ] ;
char * event = argv [ 8 ] ;
char * contact = argv [ 9 ] ;
char * callid = argv [ 10 ] ;
char * full_from = argv [ 11 ] ;
char * full_via = argv [ 12 ] ;
2006-10-19 19:39:18 +00:00
nua_handle_t * nh ;
char * to ;
char * open ;
2006-11-14 18:12:17 +00:00
char * tmp ;
2006-10-23 20:28:55 +00:00
2006-10-20 06:17:00 +00:00
if ( ! rpid ) {
rpid = " unknown " ;
}
2006-10-19 19:39:18 +00:00
if ( in ) {
2006-10-20 06:17:00 +00:00
note = switch_mprintf ( " <dm:note>%s</dm:note> " , status ) ;
2006-10-19 19:39:18 +00:00
open = " open " ;
} else {
note = NULL ;
open = " closed " ;
}
2007-03-29 22:31:56 +00:00
if ( ! strcasecmp ( sub_to_host , host ) ) {
/* same host */
2006-12-19 17:29:33 +00:00
id = switch_mprintf ( " sip:%s+%s@%s " , proto , sub_to_user , sub_to_host ) ;
} else if ( strcasecmp ( proto , SOFIA_CHAT_PROTO ) ) {
2007-03-29 22:31:56 +00:00
/*encapsulate */
2006-10-19 19:39:18 +00:00
id = switch_mprintf ( " sip:%s+%s+%s@%s " , proto , sub_to_user , sub_to_host , host ) ;
} else {
id = switch_mprintf ( " sip:%s@%s " , sub_to_user , sub_to_host ) ;
}
to = switch_mprintf ( " sip:%s@%s " , user , host ) ;
pl = switch_mprintf ( " <?xml version='1.0' encoding='UTF-8'?> \r \n "
2007-03-29 22:31:56 +00:00
" <presence xmlns='urn:ietf:params:xml:ns:pidf' \r \n "
" xmlns:dm='urn:ietf:params:xml:ns:pidf:data-model' \r \n "
" xmlns:rpid='urn:ietf:params:xml:ns:pidf:rpid' \r \n "
" xmlns:c='urn:ietf:params:xml:ns:pidf:cipid' \r \n "
" entity='pres:%s'> \r \n "
" <tuple id='t6a5ed77e'> \r \n "
" <status> \r \n "
" <basic>%s</basic> \r \n "
" </status> \r \n "
" </tuple> \r \n "
" <dm:person id='p06360c4a'> \r \n "
2007-03-30 00:13:31 +00:00
" <rpid:activities> \r \n " " <rpid:%s/> \r \n " " </rpid:activities>%s</dm:person> \r \n " " </presence> " , id , open , rpid , note ) ;
2007-03-29 22:31:56 +00:00
nh = nua_handle ( profile - > nua , NULL , TAG_END ( ) ) ;
2006-11-14 18:12:17 +00:00
tmp = contact ;
contact = get_url_from_contact ( tmp , 0 ) ;
2006-10-23 20:28:55 +00:00
2006-10-19 19:39:18 +00:00
nua_notify ( nh ,
NUTAG_URL ( contact ) ,
SIPTAG_TO_STR ( full_from ) ,
2006-12-19 17:29:33 +00:00
SIPTAG_FROM_STR ( id ) ,
2006-10-19 19:39:18 +00:00
SIPTAG_CONTACT_STR ( profile - > url ) ,
SIPTAG_CALL_ID_STR ( callid ) ,
SIPTAG_VIA_STR ( full_via ) ,
SIPTAG_SUBSCRIPTION_STATE_STR ( " active;expires=3600 " ) ,
2007-03-30 00:13:31 +00:00
SIPTAG_EVENT_STR ( event ) , SIPTAG_CONTENT_TYPE_STR ( " application/pidf+xml " ) , SIPTAG_PAYLOAD_STR ( pl ) , TAG_END ( ) ) ;
2006-10-19 19:39:18 +00:00
switch_safe_free ( id ) ;
switch_safe_free ( note ) ;
switch_safe_free ( pl ) ;
switch_safe_free ( to ) ;
return 0 ;
}
2006-10-12 00:59:09 +00:00
static void sip_i_subscribe ( int status ,
2007-03-29 22:31:56 +00:00
char const * phrase ,
2007-03-30 00:13:31 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] )
2006-10-12 00:59:09 +00:00
{
2007-03-29 22:31:56 +00:00
if ( sip ) {
long exp , exp_raw ;
sip_to_t const * to = sip - > sip_to ;
sip_from_t const * from = sip - > sip_from ;
sip_contact_t const * contact = sip - > sip_contact ;
char * from_user = NULL ;
char * from_host = NULL ;
char * to_user = NULL ;
char * to_host = NULL ;
char * sql , * event = NULL ;
char * proto = " sip " ;
char * d_user = NULL ;
char * contact_str = " " ;
char * call_id = NULL ;
char * to_str = NULL ;
char * full_from = NULL ;
char * full_via = NULL ;
switch_core_db_t * db ;
char * errmsg ;
char * sstr ;
const char * display = " \" user \" " ;
switch_event_t * sevent ;
if ( contact ) {
char * port = ( char * ) contact - > m_url - > url_port ;
display = contact - > m_display ;
if ( switch_strlen_zero ( display ) ) {
if ( from ) {
display = from - > a_display ;
if ( switch_strlen_zero ( display ) ) {
display = " \" user \" " ;
2006-11-13 21:17:57 +00:00
}
2006-10-15 05:10:34 +00:00
}
2007-03-29 22:31:56 +00:00
} else {
display = " \" user \" " ;
2006-10-15 05:10:34 +00:00
}
2007-03-29 22:31:56 +00:00
if ( ! port ) {
port = SOFIA_DEFAULT_PORT ;
2006-10-15 05:10:34 +00:00
}
2007-03-29 22:31:56 +00:00
if ( contact - > m_url - > url_params ) {
contact_str = switch_mprintf ( " %s <sip:%s@%s:%s;%s> " ,
2007-03-30 00:13:31 +00:00
display , contact - > m_url - > url_user , contact - > m_url - > url_host , port , contact - > m_url - > url_params ) ;
2007-03-29 22:31:56 +00:00
} else {
2007-03-30 00:13:31 +00:00
contact_str = switch_mprintf ( " %s <sip:%s@%s:%s> " , display , contact - > m_url - > url_user , contact - > m_url - > url_host , port ) ;
2006-10-15 05:10:34 +00:00
}
2007-03-29 22:31:56 +00:00
}
2006-10-15 05:10:34 +00:00
2007-03-29 22:31:56 +00:00
if ( to ) {
to_str = switch_mprintf ( " sip:%s@%s " , to - > a_url - > url_user , to - > a_url - > url_host ) ; //, to->a_url->url_port);
}
2006-10-22 04:37:19 +00:00
2007-03-29 22:31:56 +00:00
if ( to ) {
to_user = ( char * ) to - > a_url - > url_user ;
to_host = ( char * ) to - > a_url - > url_host ;
}
2006-10-22 04:37:19 +00:00
2007-03-29 22:31:56 +00:00
if ( strstr ( to_user , " ext+ " ) | | strstr ( to_user , " user+ " ) | | strstr ( to_user , " conf+ " ) ) {
char proto [ 80 ] ;
char * p ;
switch_copy_string ( proto , to_user , sizeof ( proto ) ) ;
if ( ( p = strchr ( proto , ' + ' ) ) ) {
* p = ' \0 ' ;
2006-10-22 04:37:19 +00:00
}
2007-03-29 22:31:56 +00:00
if ( switch_event_create ( & sevent , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( sevent , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
switch_event_add_header ( sevent , SWITCH_STACK_BOTTOM , " login " , " %s " , profile - > name ) ;
switch_event_add_header ( sevent , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , to_user , to_host ) ;
switch_event_add_header ( sevent , SWITCH_STACK_BOTTOM , " rpid " , " unknown " ) ;
switch_event_add_header ( sevent , SWITCH_STACK_BOTTOM , " status " , " Click To Call " ) ;
switch_event_fire ( & sevent ) ;
}
}
2006-10-15 05:10:34 +00:00
2007-03-29 22:31:56 +00:00
if ( strchr ( to_user , ' + ' ) ) {
char * h ;
if ( ( proto = ( d_user = strdup ( to_user ) ) ) ) {
if ( ( to_user = strchr ( d_user , ' + ' ) ) ) {
* to_user + + = ' \0 ' ;
if ( ( h = strchr ( to_user , ' + ' ) ) | | ( h = strchr ( to_user , ' @ ' ) ) ) {
* h + + = ' \0 ' ;
to_host = h ;
}
2006-10-15 05:10:34 +00:00
}
}
2007-03-29 22:31:56 +00:00
if ( ! ( proto & & to_user & & to_host ) ) {
nua_respond ( nh , SIP_404_NOT_FOUND , NUTAG_WITH_THIS ( nua ) , TAG_END ( ) ) ;
goto end ;
2006-10-15 05:10:34 +00:00
}
2007-03-29 22:31:56 +00:00
}
2006-10-15 05:10:34 +00:00
2007-03-29 22:31:56 +00:00
call_id = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_call_id ) ;
event = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_event ) ;
full_from = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_from ) ;
full_via = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_via ) ;
2006-10-20 06:17:00 +00:00
2007-03-29 22:31:56 +00:00
exp_raw = ( sip - > sip_expires ? sip - > sip_expires - > ex_delta : 3600 ) ;
exp = ( long ) time ( NULL ) + exp_raw ;
2006-10-15 05:10:34 +00:00
2007-03-29 22:31:56 +00:00
if ( sip & & sip - > sip_from ) {
from_user = ( char * ) sip - > sip_from - > a_url - > url_user ;
from_host = ( char * ) sip - > sip_from - > a_url - > url_host ;
} else {
from_user = " n/a " ;
from_host = " n/a " ;
}
if ( ( sql = switch_mprintf ( " delete from sip_subscriptions where "
" proto='%q' and user='%q' and host='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q'; \n "
" insert into sip_subscriptions values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld) " ,
proto ,
from_user ,
from_host ,
to_user ,
2007-03-30 00:13:31 +00:00
to_host , event , proto , from_user , from_host , to_user , to_host , event , contact_str , call_id , full_from , full_via , exp ) ) ) {
2007-03-29 22:31:56 +00:00
execute_sql ( profile - > dbname , sql , profile - > ireg_mutex ) ;
switch_safe_free ( sql ) ;
}
2006-10-23 20:28:55 +00:00
2007-03-29 22:31:56 +00:00
sstr = switch_mprintf ( " active;expires=%ld " , exp_raw ) ;
2006-10-23 20:28:55 +00:00
2007-03-29 22:31:56 +00:00
nua_respond ( nh , SIP_202_ACCEPTED ,
NUTAG_WITH_THIS ( nua ) ,
2007-03-30 00:13:31 +00:00
SIPTAG_SUBSCRIPTION_STATE_STR ( sstr ) , SIPTAG_FROM ( sip - > sip_to ) , SIPTAG_TO ( sip - > sip_from ) , SIPTAG_CONTACT_STR ( to_str ) , TAG_END ( ) ) ;
2006-10-15 05:10:34 +00:00
2007-03-29 22:31:56 +00:00
switch_safe_free ( sstr ) ;
if ( ! ( db = switch_core_db_open_file ( profile - > dbname ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB %s \n " , profile - > dbname ) ;
goto end ;
2006-10-15 05:10:34 +00:00
}
2007-03-30 00:13:31 +00:00
if ( ( sql = switch_mprintf ( " select * from sip_subscriptions where user='%q' and host='%q' " , to_user , to_host , to_user , to_host ) ) ) {
2007-03-29 22:31:56 +00:00
switch_mutex_lock ( profile - > ireg_mutex ) ;
switch_core_db_exec ( db , sql , sub_reg_callback , profile , & errmsg ) ;
switch_mutex_unlock ( profile - > ireg_mutex ) ;
switch_safe_free ( sql ) ;
}
switch_core_db_close ( db ) ;
end :
if ( event ) {
su_free ( profile - > home , event ) ;
}
if ( call_id ) {
su_free ( profile - > home , call_id ) ;
}
if ( full_from ) {
su_free ( profile - > home , full_from ) ;
}
if ( full_via ) {
su_free ( profile - > home , full_via ) ;
}
switch_safe_free ( d_user ) ;
switch_safe_free ( to_str ) ;
switch_safe_free ( contact_str ) ;
}
2006-10-12 00:59:09 +00:00
}
static void sip_r_subscribe ( int status ,
2007-03-29 22:31:56 +00:00
char const * phrase ,
2007-03-30 00:13:31 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] )
2006-10-12 00:59:09 +00:00
{
}
2006-09-29 01:07:51 +00:00
2006-10-03 04:08:30 +00:00
/*---------------------------------------*/
2007-03-30 00:13:31 +00:00
static void sip_i_refer ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , switch_core_session_t * session , sip_t const * sip , tagi_t tags [ ] )
2006-10-03 04:08:30 +00:00
{
/* Incoming refer */
sip_from_t const * from ;
sip_to_t const * to ;
sip_refer_to_t const * refer_to ;
2007-03-29 22:31:56 +00:00
private_object_t * tech_pvt = NULL ;
char * etmp = NULL , * exten = NULL ;
switch_channel_t * channel_a = NULL , * channel_b = NULL ;
tech_pvt = switch_core_session_get_private ( session ) ;
channel_a = switch_core_session_get_channel ( session ) ;
if ( ! sip - > sip_cseq | | ! ( etmp = switch_mprintf ( " refer;id=%u " , sip - > sip_cseq - > cs_seq ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Memory Error! \n " ) ;
goto done ;
}
if ( switch_channel_test_flag ( channel_a , CF_NOMEDIA ) ) {
nua_notify ( tech_pvt - > nh , SIPTAG_CONTENT_TYPE_STR ( " message/sipfrag " ) ,
2007-03-30 00:13:31 +00:00
NUTAG_SUBSTATE ( nua_substate_terminated ) , SIPTAG_PAYLOAD_STR ( " SIP/2.0 403 Forbidden " ) , SIPTAG_EVENT_STR ( etmp ) , TAG_END ( ) ) ;
2007-03-29 22:31:56 +00:00
goto done ;
}
from = sip - > sip_from ;
to = sip - > sip_to ;
if ( ( refer_to = sip - > sip_refer_to ) ) {
if ( profile - > pflags & PFLAG_FULL_ID ) {
exten = switch_mprintf ( " %s@%s " , ( char * ) refer_to - > r_url - > url_user , ( char * ) refer_to - > r_url - > url_host ) ;
} else {
exten = ( char * ) refer_to - > r_url - > url_user ;
}
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Process REFER to [%s@%s] \n " , exten , ( char * ) refer_to - > r_url - > url_host ) ;
2007-03-29 22:31:56 +00:00
if ( refer_to - > r_url - > url_headers ) {
sip_replaces_t * replaces ;
nua_handle_t * bnh ;
char * rep ;
if ( ( rep = strchr ( refer_to - > r_url - > url_headers , ' = ' ) ) ) {
char * br_a = NULL , * br_b = NULL ;
char * buf ;
rep + + ;
if ( ( buf = switch_core_session_alloc ( session , strlen ( rep ) + 1 ) ) ) {
rep = url_unescape ( buf , ( const char * ) rep ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Replaces: [%s] \n " , rep ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Memory Error! \n " ) ;
goto done ;
}
if ( ( replaces = sip_replaces_make ( tech_pvt - > home , rep ) )
& & ( bnh = nua_handle_by_replaces ( nua , replaces ) ) ) {
sofia_private_t * b_private = NULL ;
private_object_t * b_tech_pvt = NULL ;
switch_core_session_t * b_session = NULL ;
switch_channel_set_variable ( channel_a , SOFIA_REPLACES_HEADER , rep ) ;
if ( ( b_private = nua_handle_magic ( bnh ) ) ) {
if ( ! ( b_session = switch_core_session_locate ( b_private - > uuid ) ) ) {
goto done ;
}
b_tech_pvt = ( private_object_t * ) switch_core_session_get_private ( b_session ) ;
channel_b = switch_core_session_get_channel ( b_session ) ;
br_a = switch_channel_get_variable ( channel_a , SWITCH_SIGNAL_BOND_VARIABLE ) ;
br_b = switch_channel_get_variable ( channel_b , SWITCH_SIGNAL_BOND_VARIABLE ) ;
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Attended Transfer [%s][%s] \n " , br_a , br_b ) ;
2007-03-29 22:31:56 +00:00
if ( br_a & & br_b ) {
switch_ivr_uuid_bridge ( br_a , br_b ) ;
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel_b , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " ATTENDED_TRANSFER " ) ;
2007-03-29 22:31:56 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_BYE ) ;
switch_set_flag_locked ( b_tech_pvt , TFLAG_BYE ) ;
nua_notify ( tech_pvt - > nh , SIPTAG_CONTENT_TYPE_STR ( " message/sipfrag " ) ,
2007-03-30 00:13:31 +00:00
NUTAG_SUBSTATE ( nua_substate_terminated ) , SIPTAG_PAYLOAD_STR ( " SIP/2.0 200 OK " ) , SIPTAG_EVENT_STR ( etmp ) , TAG_END ( ) ) ;
2007-03-29 22:31:56 +00:00
} else {
if ( ! br_a & & ! br_b ) {
switch_set_flag_locked ( tech_pvt , TFLAG_NOHUP ) ;
switch_set_flag_locked ( b_tech_pvt , TFLAG_XFER ) ;
2007-03-30 00:13:31 +00:00
b_tech_pvt - > xferto = switch_core_session_strdup ( b_session , switch_core_session_get_uuid ( session ) ) ;
2007-03-29 22:31:56 +00:00
} else if ( ! br_a & & br_b ) {
switch_core_session_t * br_b_session ;
if ( ( br_b_session = switch_core_session_locate ( br_b ) ) ) {
private_object_t * br_b_tech_pvt = switch_core_session_get_private ( br_b_session ) ;
switch_channel_t * br_b_channel = switch_core_session_get_channel ( br_b_session ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_NOHUP ) ;
switch_channel_clear_state_handler ( br_b_channel , NULL ) ;
switch_channel_set_state_flag ( br_b_channel , CF_TRANSFER ) ;
switch_channel_set_state ( br_b_channel , CS_TRANSMIT ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_REINVITE ) ;
2007-03-30 00:13:31 +00:00
tech_pvt - > local_sdp_audio_ip = switch_core_session_strdup ( session , b_tech_pvt - > local_sdp_audio_ip ) ;
2007-03-29 22:31:56 +00:00
tech_pvt - > local_sdp_audio_port = b_tech_pvt - > local_sdp_audio_port ;
2007-03-30 00:13:31 +00:00
tech_pvt - > remote_sdp_audio_ip = switch_core_session_strdup ( session , br_b_tech_pvt - > remote_sdp_audio_ip ) ;
2007-03-29 22:31:56 +00:00
tech_pvt - > remote_sdp_audio_port = br_b_tech_pvt - > remote_sdp_audio_port ;
activate_rtp ( tech_pvt ) ;
2007-03-30 00:13:31 +00:00
br_b_tech_pvt - > kick = switch_core_session_strdup ( br_b_session , switch_core_session_get_uuid ( session ) ) ;
2007-03-29 22:31:56 +00:00
switch_core_session_rwunlock ( br_b_session ) ;
}
switch_channel_hangup ( channel_b , SWITCH_CAUSE_ATTENDED_TRANSFER ) ;
}
switch_set_flag_locked ( tech_pvt , TFLAG_BYE ) ;
nua_notify ( tech_pvt - > nh , SIPTAG_CONTENT_TYPE_STR ( " message/sipfrag " ) ,
2007-03-30 00:13:31 +00:00
NUTAG_SUBSTATE ( nua_substate_terminated ) , SIPTAG_PAYLOAD_STR ( " SIP/2.0 200 OK " ) , SIPTAG_EVENT_STR ( etmp ) , TAG_END ( ) ) ;
2007-03-29 22:31:56 +00:00
}
if ( b_session ) {
switch_core_session_rwunlock ( b_session ) ;
}
}
nua_handle_unref ( bnh ) ;
} else { /* the other channel is on a different box, we have to go find them */
if ( exten & & ( br_a = switch_channel_get_variable ( channel_a , SWITCH_SIGNAL_BOND_VARIABLE ) ) ) {
switch_core_session_t * a_session ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
if ( ( a_session = switch_core_session_locate ( br_a ) ) ) {
switch_core_session_t * tsession ;
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING ;
uint32_t timeout = 60 ;
char * tuuid_str ;
channel = switch_core_session_get_channel ( a_session ) ;
exten = switch_mprintf ( " sofia/%s/%s@%s:%s " ,
profile - > name ,
2007-03-30 00:13:31 +00:00
( char * ) refer_to - > r_url - > url_user , ( char * ) refer_to - > r_url - > url_host , refer_to - > r_url - > url_port ) ;
2007-03-29 22:31:56 +00:00
switch_channel_set_variable ( channel , SOFIA_REPLACES_HEADER , rep ) ;
if ( switch_ivr_originate ( a_session ,
2007-03-30 00:13:31 +00:00
& tsession , & cause , exten , timeout , & noop_state_handler , NULL , NULL , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot Create Outgoing Channel! [%s] \n " , exten ) ;
2007-03-29 22:31:56 +00:00
nua_notify ( tech_pvt - > nh , SIPTAG_CONTENT_TYPE_STR ( " message/sipfrag " ) ,
NUTAG_SUBSTATE ( nua_substate_terminated ) ,
2007-03-30 00:13:31 +00:00
SIPTAG_PAYLOAD_STR ( " SIP/2.0 403 Forbidden " ) , SIPTAG_EVENT_STR ( etmp ) , TAG_END ( ) ) ;
2007-03-29 22:31:56 +00:00
goto done ;
}
switch_core_session_rwunlock ( a_session ) ;
tuuid_str = switch_core_session_get_uuid ( tsession ) ;
switch_ivr_uuid_bridge ( br_a , tuuid_str ) ;
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel_a , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " ATTENDED_TRANSFER " ) ;
2007-03-29 22:31:56 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_BYE ) ;
nua_notify ( tech_pvt - > nh , SIPTAG_CONTENT_TYPE_STR ( " message/sipfrag " ) ,
2007-03-30 00:13:31 +00:00
NUTAG_SUBSTATE ( nua_substate_terminated ) , SIPTAG_PAYLOAD_STR ( " SIP/2.0 200 OK " ) , SIPTAG_EVENT_STR ( etmp ) , TAG_END ( ) ) ;
2007-03-29 22:31:56 +00:00
} else {
goto error ;
}
} else {
error :
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Transfer! [%s] \n " , br_a ) ;
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel_a , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " ATTENDED_TRANSFER_ERROR " ) ;
2007-03-29 22:31:56 +00:00
nua_notify ( tech_pvt - > nh , SIPTAG_CONTENT_TYPE_STR ( " message/sipfrag " ) ,
2007-03-30 00:13:31 +00:00
NUTAG_SUBSTATE ( nua_substate_terminated ) , SIPTAG_PAYLOAD_STR ( " SIP/2.0 403 Forbidden " ) , SIPTAG_EVENT_STR ( etmp ) , TAG_END ( ) ) ;
2007-03-29 22:31:56 +00:00
}
}
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot parse Replaces! \n " ) ;
}
goto done ;
}
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing Refer-To \n " ) ;
goto done ;
}
if ( exten ) {
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
char * br ;
if ( ( br = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ) ) {
switch_core_session_t * b_session ;
if ( ( b_session = switch_core_session_locate ( br ) ) ) {
switch_channel_set_variable ( channel , " TRANSFER_FALLBACK " , from - > a_user ) ;
switch_ivr_session_transfer ( b_session , exten , profile - > dialplan , profile - > context ) ;
switch_core_session_rwunlock ( b_session ) ;
}
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " BLIND_TRANSFER " ) ;
/*
nua_notify ( tech_pvt - > nh , SIPTAG_CONTENT_TYPE_STR ( " message/sipfrag " ) ,
NUTAG_SUBSTATE ( nua_substate_terminated ) ,
SIPTAG_PAYLOAD_STR ( " SIP/2.0 200 OK " ) ,
SIPTAG_EVENT_STR ( etmp ) ,
TAG_END ( ) ) ;
*/
} else {
2007-03-30 00:13:31 +00:00
exten = switch_mprintf ( " sip:%s@%s:%s " , ( char * ) refer_to - > r_url - > url_user , ( char * ) refer_to - > r_url - > url_host , refer_to - > r_url - > url_port ) ;
2007-03-29 22:31:56 +00:00
tech_pvt - > dest = switch_core_session_strdup ( session , exten ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_NOHUP ) ;
/*
nua_notify ( tech_pvt - > nh , SIPTAG_CONTENT_TYPE_STR ( " message/sipfrag " ) ,
NUTAG_SUBSTATE ( nua_substate_terminated ) ,
SIPTAG_PAYLOAD_STR ( " SIP/2.0 200 OK " ) ,
SIPTAG_EVENT_STR ( etmp ) ,
TAG_END ( ) ) ;
*/
do_xfer_invite ( session ) ;
}
}
done :
if ( exten & & strchr ( exten , ' @ ' ) ) {
switch_safe_free ( exten ) ;
}
if ( etmp ) {
switch_safe_free ( etmp ) ;
}
2006-10-03 04:08:30 +00:00
}
2006-10-15 05:10:34 +00:00
2007-03-30 00:13:31 +00:00
static void sip_i_publish ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] )
2006-10-15 05:10:34 +00:00
{
if ( sip ) {
sip_from_t const * from = sip - > sip_from ;
char * from_user = NULL ;
char * from_host = NULL ;
2006-10-20 06:17:00 +00:00
char * rpid = " unknown " ;
2006-10-15 05:10:34 +00:00
sip_payload_t * payload = sip - > sip_payload ;
char * event_type ;
if ( from ) {
from_user = ( char * ) from - > a_url - > url_user ;
from_host = ( char * ) from - > a_url - > url_host ;
}
if ( payload ) {
2006-10-20 06:17:00 +00:00
switch_xml_t xml , note , person , tuple , status , basic , act ;
2006-10-15 05:10:34 +00:00
switch_event_t * event ;
uint8_t in = 0 ;
2006-10-19 19:39:18 +00:00
char * sql ;
2006-10-15 05:10:34 +00:00
if ( ( xml = switch_xml_parse_str ( payload - > pl_data , strlen ( payload - > pl_data ) ) ) ) {
char * status_txt = " " , * note_txt = " " ;
2007-03-29 22:31:56 +00:00
if ( ( tuple = switch_xml_child ( xml , " tuple " ) ) & & ( status = switch_xml_child ( tuple , " status " ) )
& & ( basic = switch_xml_child ( status , " basic " ) ) ) {
2006-10-15 05:10:34 +00:00
status_txt = basic - > txt ;
}
2007-03-29 22:31:56 +00:00
2006-10-15 05:10:34 +00:00
if ( ( person = switch_xml_child ( xml , " dm:person " ) ) & & ( note = switch_xml_child ( person , " dm:note " ) ) ) {
note_txt = note - > txt ;
}
2006-10-20 06:17:00 +00:00
if ( person & & ( act = switch_xml_child ( person , " rpid:activities " ) ) ) {
if ( ( rpid = strchr ( act - > child - > name , ' : ' ) ) ) {
rpid + + ;
} else {
rpid = act - > child - > name ;
}
}
2006-10-15 05:10:34 +00:00
if ( ! strcasecmp ( status_txt , " open " ) ) {
if ( switch_strlen_zero ( note_txt ) ) {
note_txt = " Available " ;
}
in = 1 ;
} else if ( ! strcasecmp ( status_txt , " closed " ) ) {
if ( switch_strlen_zero ( note_txt ) ) {
note_txt = " Unavailable " ;
}
}
2007-03-29 22:31:56 +00:00
if ( ( sql =
switch_mprintf ( " update sip_registrations set status='%q',rpid='%q' where user='%q' and host='%q' " ,
note_txt , rpid , from_user , from_host ) ) ) {
2006-10-19 19:39:18 +00:00
execute_sql ( profile - > dbname , sql , profile - > ireg_mutex ) ;
switch_safe_free ( sql ) ;
}
2007-03-29 22:31:56 +00:00
event_type = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_event ) ;
2006-10-15 05:10:34 +00:00
if ( in ) {
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
2006-10-20 22:11:26 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
2006-10-20 06:17:00 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " rpid " , " %s " , rpid ) ;
2006-10-15 05:10:34 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " login " , " %s " , profile - > url ) ;
2006-10-20 22:11:26 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , from_user , from_host ) ;
2007-03-29 22:31:56 +00:00
2006-10-18 22:57:35 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " status " , " %s " , note_txt ) ;
2006-10-15 05:10:34 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " event_type " , " %s " , event_type ) ;
switch_event_fire ( & event ) ;
}
} else {
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_OUT ) = = SWITCH_STATUS_SUCCESS ) {
2006-10-20 22:11:26 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
2006-10-20 06:17:00 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " rpid " , " %s " , rpid ) ;
2006-10-15 05:10:34 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " login " , " %s " , profile - > url ) ;
2006-10-20 22:11:26 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , from_user , from_host ) ;
2006-10-18 22:57:35 +00:00
2006-10-15 05:10:34 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " event_type " , " %s " , event_type ) ;
switch_event_fire ( & event ) ;
}
}
if ( event_type ) {
su_free ( profile - > home , event_type ) ;
2007-03-29 22:31:56 +00:00
}
2006-10-15 05:10:34 +00:00
switch_xml_free ( xml ) ;
}
2007-03-29 22:31:56 +00:00
2006-10-15 05:10:34 +00:00
}
2007-03-29 22:31:56 +00:00
2006-10-15 05:10:34 +00:00
}
2006-10-23 20:28:55 +00:00
nua_respond ( nh , SIP_200_OK , NUTAG_WITH_THIS ( nua ) , TAG_END ( ) ) ;
2006-10-15 05:10:34 +00:00
}
2007-03-30 00:13:31 +00:00
static void sip_i_info ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , switch_core_session_t * session , sip_t const * sip , tagi_t tags [ ] )
2007-03-29 22:31:56 +00:00
{
2006-10-24 22:11:25 +00:00
//placeholder for string searching
char * signal_ptr ;
//Try and find signal information in the payload
signal_ptr = strstr ( sip - > sip_payload - > pl_data , " Signal= " ) ;
//See if we found a match
2007-03-29 22:31:56 +00:00
if ( signal_ptr ) {
2006-10-24 22:11:25 +00:00
struct private_object * tech_pvt = NULL ;
switch_channel_t * channel = NULL ;
2007-03-29 22:31:56 +00:00
char dtmf_digit [ 2 ] = { 0 , 0 } ;
2006-10-24 22:11:25 +00:00
//Get the channel
channel = switch_core_session_get_channel ( session ) ;
//Barf if we didn't get it
assert ( channel ! = NULL ) ;
//make sure we have our privates
tech_pvt = switch_core_session_get_private ( session ) ;
//Barf if we didn't get it
assert ( tech_pvt ! = NULL ) ;
//move signal_ptr where we need it (right past Signal=)
signal_ptr = signal_ptr + 7 ;
//put the digit somewhere we can muck with
strncpy ( dtmf_digit , signal_ptr , 1 ) ;
//queue it up
switch_channel_queue_dtmf ( channel , dtmf_digit ) ;
2007-03-29 22:31:56 +00:00
2006-10-24 22:11:25 +00:00
//print debug info
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " INFO DTMF(%s) \n " , dtmf_digit ) ;
2007-03-29 22:31:56 +00:00
} else { //unknown info type
2006-10-24 22:11:25 +00:00
sip_from_t const * from ;
from = sip - > sip_from ;
//print in the logs if something comes through we don't understand
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Unknown INFO Recieved: %s%s " URL_PRINT_FORMAT " [%s] \n " ,
2007-03-30 00:13:31 +00:00
from - > a_display ? from - > a_display : " " , from - > a_display ? " " : " " , URL_PRINT_ARGS ( from - > a_url ) , sip - > sip_payload - > pl_data ) ;
2006-10-24 22:11:25 +00:00
}
return ;
}
2006-10-15 05:10:34 +00:00
2007-02-25 16:53:17 +00:00
2007-03-02 09:11:50 +00:00
# define url_set_chanvars(session, url, varprefix) _url_set_chanvars(session, url, #varprefix "_user", #varprefix "_host", #varprefix "_port", #varprefix "_uri")
2007-03-29 22:31:56 +00:00
static const char * _url_set_chanvars ( switch_core_session_t * session , url_t * url , const char * user_var ,
const char * host_var , const char * port_var , const char * uri_var )
2007-02-25 16:53:17 +00:00
{
const char * user = NULL , * host = NULL , * port = NULL ;
char * uri = NULL ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
if ( url ) {
user = url - > url_user ;
host = url - > url_host ;
port = url - > url_port ;
}
if ( user ) {
switch_channel_set_variable ( channel , user_var , user ) ;
}
if ( ! port ) {
2007-03-19 21:09:53 +00:00
port = SOFIA_DEFAULT_PORT ;
2007-02-25 16:53:17 +00:00
}
switch_channel_set_variable ( channel , port_var , port ) ;
if ( host ) {
if ( user ) {
uri = switch_core_session_sprintf ( session , " %s@%s:%s " , user , host , port ) ;
} else {
uri = switch_core_session_sprintf ( session , " %s:%s " , host , port ) ;
}
switch_channel_set_variable_nodup ( channel , uri_var , uri ) ;
switch_channel_set_variable ( channel , host_var , host ) ;
}
return uri ;
}
2007-03-29 22:31:56 +00:00
static void process_rpid ( sip_unknown_t * un , private_object_t * tech_pvt )
2007-02-25 16:53:17 +00:00
{
int argc , x , screen = 1 ;
char * mydata , * argv [ 10 ] = { 0 } ;
2007-03-29 22:31:56 +00:00
if ( ! switch_strlen_zero ( un - > un_value ) ) {
2007-02-25 16:53:17 +00:00
if ( ( mydata = strdup ( un - > un_value ) ) ) {
2007-03-29 22:31:56 +00:00
argc = switch_separate_string ( mydata , ' ; ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
2007-02-25 16:53:17 +00:00
// Do We really need this at this time
// clid_uri = argv[0];
2007-03-29 22:31:56 +00:00
for ( x = 1 ; x < argc & & argv [ x ] ; x + + ) {
2007-02-25 16:53:17 +00:00
// we dont need to do anything with party yet we should only be seeing party=calling here anyway
// maybe thats a dangerous assumption bit oh well yell at me later
// if (!strncasecmp(argv[x], "party", 5)) {
2007-03-29 22:31:56 +00:00
// party = argv[x];
2007-02-25 16:53:17 +00:00
// } else
if ( ! strncasecmp ( argv [ x ] , " privacy= " , 8 ) ) {
char * arg = argv [ x ] + 9 ;
if ( ! strcasecmp ( arg , " yes " ) ) {
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER ) ;
} else if ( ! strcasecmp ( arg , " full " ) ) {
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER ) ;
} else if ( ! strcasecmp ( arg , " name " ) ) {
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_HIDE_NAME ) ;
} else if ( ! strcasecmp ( arg , " number " ) ) {
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_HIDE_NUMBER ) ;
} else {
switch_clear_flag ( tech_pvt - > caller_profile , SWITCH_CPF_HIDE_NAME ) ;
switch_clear_flag ( tech_pvt - > caller_profile , SWITCH_CPF_HIDE_NUMBER ) ;
}
} else if ( ! strncasecmp ( argv [ x ] , " screen= " , 7 ) & & screen > 0 ) {
char * arg = argv [ x ] + 8 ;
if ( ! strcasecmp ( arg , " no " ) ) {
screen = 0 ;
switch_clear_flag ( tech_pvt - > caller_profile , SWITCH_CPF_SCREEN ) ;
}
}
}
free ( mydata ) ;
}
}
}
2007-03-30 00:13:31 +00:00
static void sip_i_invite ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] )
2006-09-29 01:07:51 +00:00
{
2006-12-28 19:38:35 +00:00
switch_core_session_t * session = NULL ;
2006-09-29 18:12:31 +00:00
char key [ 128 ] = " " ;
2006-10-16 04:39:00 +00:00
sip_unknown_t * un ;
2007-02-25 16:53:17 +00:00
private_object_t * tech_pvt = NULL ;
switch_channel_t * channel = NULL ;
const char * channel_name = NULL ;
const char * displayname = NULL ;
const char * destination_number = NULL ;
const char * from_user = NULL , * from_host = NULL ;
2007-03-20 23:09:35 +00:00
const char * context = NULL ;
2007-02-08 20:16:08 +00:00
char network_ip [ 80 ] ;
2007-03-05 06:04:37 +00:00
if ( ! sip | | ! sip - > sip_request | | ! sip - > sip_request - > rq_method_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Received an invalid packet! \n " ) ;
2007-02-25 16:53:17 +00:00
nua_respond ( nh , SIP_500_INTERNAL_SERVER_ERROR , TAG_END ( ) ) ;
return ;
}
2006-09-29 01:07:51 +00:00
2007-03-05 06:04:37 +00:00
2007-02-25 16:53:17 +00:00
if ( ! ( sip - > sip_contact & & sip - > sip_contact - > m_url ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " NO CONTACT! \n " ) ;
2007-02-10 23:16:43 +00:00
nua_respond ( nh , 400 , " Missing Contact Header " , TAG_END ( ) ) ;
2007-02-25 16:53:17 +00:00
return ;
}
2007-02-02 00:42:20 +00:00
2007-02-25 16:53:17 +00:00
if ( ( profile - > pflags & PFLAG_AUTH_CALLS ) ) {
if ( handle_register ( nua , profile , nh , sip , REG_INVITE , key , sizeof ( key ) ) ) {
return ;
}
}
2006-09-29 01:07:51 +00:00
2007-02-25 16:53:17 +00:00
if ( ! ( session = switch_core_session_request ( & sofia_endpoint_interface , NULL ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Session Alloc Failed! \n " ) ;
2007-02-10 23:16:43 +00:00
nua_respond ( nh , SIP_503_SERVICE_UNAVAILABLE , TAG_END ( ) ) ;
return ;
2007-02-25 16:53:17 +00:00
}
2006-09-29 01:07:51 +00:00
2007-02-25 16:53:17 +00:00
if ( ! ( tech_pvt = ( private_object_t * ) switch_core_session_alloc ( session , sizeof ( private_object_t ) ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Hey where is my memory pool? \n " ) ;
2007-03-09 17:38:58 +00:00
nua_respond ( nh , SIP_503_SERVICE_UNAVAILABLE , TAG_END ( ) ) ;
2007-02-25 16:53:17 +00:00
terminate_session ( & session , SWITCH_CAUSE_SWITCH_CONGESTION , __LINE__ ) ;
return ;
}
2006-09-29 18:12:31 +00:00
2007-02-25 16:53:17 +00:00
if ( ! switch_strlen_zero ( key ) ) {
tech_pvt - > key = switch_core_session_strdup ( session , key ) ;
}
2006-12-28 19:38:35 +00:00
2007-03-30 00:13:31 +00:00
get_addr ( network_ip , sizeof ( network_ip ) , & ( ( struct sockaddr_in * ) msg_addrinfo ( nua_current_request ( nua ) ) - > ai_addr ) - > sin_addr ) ;
2007-02-08 20:16:08 +00:00
2007-02-25 16:53:17 +00:00
channel = switch_core_session_get_channel ( session ) ;
2006-10-05 15:07:45 +00:00
2007-02-25 16:53:17 +00:00
if ( sip - > sip_from & & sip - > sip_from - > a_url ) {
from_user = sip - > sip_from - > a_url - > url_user ;
from_host = sip - > sip_from - > a_url - > url_host ;
2007-03-02 09:11:50 +00:00
channel_name = url_set_chanvars ( session , sip - > sip_from - > a_url , sip_from ) ;
2006-10-19 16:33:54 +00:00
2007-02-25 16:53:17 +00:00
if ( ! switch_strlen_zero ( from_user ) ) {
if ( * from_user = = ' + ' ) {
2007-03-29 22:31:56 +00:00
switch_channel_set_variable ( channel , " sip_from_user_stripped " , ( const char * ) ( from_user + 1 ) ) ;
2007-02-25 16:53:17 +00:00
} else {
switch_channel_set_variable ( channel , " sip_from_user_stripped " , from_user ) ;
}
}
2006-12-29 00:57:08 +00:00
2007-02-25 16:53:17 +00:00
if ( ! switch_strlen_zero ( sip - > sip_from - > a_display ) ) {
char * tmp ;
tmp = switch_core_session_strdup ( session , sip - > sip_from - > a_display ) ;
if ( * tmp = = ' " ' ) {
char * p ;
2006-12-29 00:57:08 +00:00
2007-02-25 16:53:17 +00:00
tmp + + ;
if ( ( p = strchr ( tmp , ' " ' ) ) ) {
* p = ' \0 ' ;
}
}
displayname = tmp ;
} else {
displayname = switch_strlen_zero ( from_user ) ? " unkonwn " : from_user ;
}
}
2006-12-29 00:57:08 +00:00
2007-03-05 06:04:37 +00:00
if ( sip - > sip_request - > rq_url ) {
2007-03-29 22:31:56 +00:00
const char * req_uri = url_set_chanvars ( session , sip - > sip_request - > rq_url , sip_req ) ;
if ( profile - > pflags & PFLAG_FULL_ID ) {
2007-02-25 16:53:17 +00:00
destination_number = req_uri ;
} else {
destination_number = sip - > sip_request - > rq_url - > url_user ;
}
}
2006-12-06 17:19:07 +00:00
2007-02-25 16:53:17 +00:00
if ( sip - > sip_to & & sip - > sip_to - > a_url ) {
2007-03-02 09:11:50 +00:00
url_set_chanvars ( session , sip - > sip_to - > a_url , sip_to ) ;
2007-02-25 16:53:17 +00:00
}
2006-12-06 17:19:07 +00:00
2007-02-25 16:53:17 +00:00
if ( sip - > sip_contact & & sip - > sip_contact - > m_url ) {
2007-03-02 09:11:50 +00:00
const char * contact_uri = url_set_chanvars ( session , sip - > sip_contact - > m_url , sip_contact ) ;
2007-02-25 16:53:17 +00:00
if ( ! channel_name ) {
channel_name = contact_uri ;
}
}
2006-11-25 16:35:56 +00:00
2007-02-25 16:53:17 +00:00
attach_private ( session , profile , tech_pvt , channel_name ) ;
tech_set_codecs ( tech_pvt ) ;
2006-11-28 16:45:25 +00:00
2007-02-28 15:48:17 +00:00
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " INBOUND CALL " ) ;
2007-02-25 16:53:17 +00:00
set_chat_hash ( tech_pvt , sip ) ;
2006-11-28 16:45:25 +00:00
2007-02-25 16:53:17 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_INB_NOMEDIA ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_NOMEDIA ) ;
switch_channel_set_flag ( channel , CF_NOMEDIA ) ;
}
2006-11-28 16:45:25 +00:00
2007-02-25 16:53:17 +00:00
if ( ! tech_pvt - > call_id & & sip - > sip_call_id & & sip - > sip_call_id - > i_id ) {
tech_pvt - > call_id = switch_core_session_strdup ( session , sip - > sip_call_id - > i_id ) ;
switch_channel_set_variable ( channel , " sip_call_id " , tech_pvt - > call_id ) ;
}
2006-11-28 16:45:25 +00:00
2007-02-25 16:53:17 +00:00
if ( sip - > sip_via ) {
if ( sip - > sip_via - > v_host ) {
switch_channel_set_variable ( channel , " sip_via_host " , sip - > sip_via - > v_host ) ;
2007-01-11 23:04:54 +00:00
}
2007-02-25 16:53:17 +00:00
if ( sip - > sip_via - > v_port ) {
switch_channel_set_variable ( channel , " sip_via_port " , sip - > sip_via - > v_port ) ;
}
if ( sip - > sip_via - > v_rport ) {
switch_channel_set_variable ( channel , " sip_via_rport " , sip - > sip_via - > v_rport ) ;
}
}
2006-12-28 19:38:35 +00:00
2007-01-15 15:40:35 +00:00
if ( sip - > sip_max_forwards ) {
2007-02-25 16:53:17 +00:00
char max_forwards [ 32 ] ;
2007-03-18 07:04:40 +00:00
snprintf ( max_forwards , sizeof ( max_forwards ) , " %lu " , sip - > sip_max_forwards - > mf_count ) ;
2007-02-25 16:53:17 +00:00
switch_channel_set_variable ( channel , SWITCH_MAX_FORWARDS_VARIABLE , max_forwards ) ;
}
2006-10-16 04:39:00 +00:00
2007-03-29 22:31:56 +00:00
2007-03-20 23:09:35 +00:00
if ( sip - > sip_request - > rq_url ) {
outbound_reg_t * gateway ;
char * from_key = switch_core_session_sprintf ( session , " sip:%s@%s " ,
( char * ) sip - > sip_request - > rq_url - > url_user ,
( char * ) sip - > sip_request - > rq_url - > url_host ) ;
2007-03-29 22:31:56 +00:00
2007-03-20 23:09:35 +00:00
if ( ( gateway = find_gateway ( from_key ) ) ) {
context = gateway - > register_context ;
switch_channel_set_variable ( channel , " sip_gateway " , gateway - > name ) ;
}
}
2007-03-29 22:31:56 +00:00
2007-03-20 23:09:35 +00:00
if ( ! context ) {
if ( profile - > context & & ! strcasecmp ( profile - > context , " _domain_ " ) ) {
context = from_host ;
} else {
context = profile - > context ;
}
2007-02-25 16:53:17 +00:00
}
2006-10-16 04:39:00 +00:00
2007-02-25 16:53:17 +00:00
tech_pvt - > caller_profile = switch_caller_profile_new ( switch_core_session_get_pool ( session ) ,
2007-03-29 22:31:56 +00:00
from_user ,
profile - > dialplan ,
2007-03-30 00:13:31 +00:00
displayname , from_user , network_ip , NULL , NULL , NULL , modname , context , destination_number ) ;
2007-02-25 16:53:17 +00:00
if ( tech_pvt - > caller_profile ) {
2007-03-29 22:31:56 +00:00
2007-02-25 16:53:17 +00:00
/* Loop thru unknown Headers Here so we can do something with them */
2007-03-29 22:31:56 +00:00
for ( un = sip - > sip_unknown ; un ; un = un - > un_next ) {
2007-02-25 16:53:17 +00:00
if ( ! strncasecmp ( un - > un_name , " Alert-Info " , 10 ) ) {
2007-03-29 22:31:56 +00:00
if ( ! switch_strlen_zero ( un - > un_value ) ) {
2007-02-25 16:53:17 +00:00
switch_channel_set_variable ( channel , " alert_info " , un - > un_value ) ;
}
} else if ( ! strncasecmp ( un - > un_name , " Remote-Party-ID " , 15 ) ) {
process_rpid ( un , tech_pvt ) ;
2007-02-13 01:22:17 +00:00
} else if ( ! strncasecmp ( un - > un_name , " X- " , 2 ) ) {
2007-03-29 22:31:56 +00:00
if ( ! switch_strlen_zero ( un - > un_value ) ) {
2007-02-13 01:22:17 +00:00
char * new_name ;
2007-02-17 00:56:16 +00:00
if ( ( new_name = switch_mprintf ( " %s%s " , SOFIA_SIP_HEADER_PREFIX , un - > un_name ) ) ) {
switch_channel_set_variable ( channel , new_name , un - > un_value ) ;
2007-02-13 01:22:17 +00:00
free ( new_name ) ;
}
}
}
2007-02-25 16:53:17 +00:00
}
2006-12-28 19:38:35 +00:00
2007-02-25 16:53:17 +00:00
switch_channel_set_caller_profile ( channel , tech_pvt - > caller_profile ) ;
}
2006-12-28 19:38:35 +00:00
2007-02-25 16:53:17 +00:00
if ( ! ( tech_pvt - > sofia_private = malloc ( sizeof ( * tech_pvt - > sofia_private ) ) ) ) {
abort ( ) ;
}
memset ( tech_pvt - > sofia_private , 0 , sizeof ( * tech_pvt - > sofia_private ) ) ;
2007-03-30 00:13:31 +00:00
switch_copy_string ( tech_pvt - > sofia_private - > uuid , switch_core_session_get_uuid ( session ) , sizeof ( tech_pvt - > sofia_private - > uuid ) ) ;
2007-02-25 16:53:17 +00:00
nua_handle_bind ( nh , tech_pvt - > sofia_private ) ;
tech_pvt - > nh = nh ;
2006-09-29 01:07:51 +00:00
}
2007-03-30 00:13:31 +00:00
static void sip_i_register ( nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] )
2006-09-29 01:07:51 +00:00
{
2007-03-29 22:31:56 +00:00
char key [ 128 ] = " " ;
2007-03-05 06:04:37 +00:00
if ( ! sip | | ! sip - > sip_request | | ! sip - > sip_request - > rq_method_name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Received an invalid packet! \n " ) ;
nua_respond ( nh , SIP_500_INTERNAL_SERVER_ERROR , TAG_END ( ) ) ;
return ;
}
if ( ! ( sip - > sip_contact & & sip - > sip_contact - > m_url ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " NO CONTACT! \n " ) ;
nua_respond ( nh , 400 , " Missing Contact Header " , TAG_END ( ) ) ;
return ;
}
2006-12-13 20:10:00 +00:00
handle_register ( nua , profile , nh , sip , REG_REGISTER , key , sizeof ( key ) ) ;
2006-09-27 03:44:14 +00:00
}
2006-09-30 00:00:07 +00:00
2006-10-12 00:59:09 +00:00
static void sip_i_options ( int status ,
char const * phrase ,
2007-03-30 00:13:31 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] )
2006-10-12 00:59:09 +00:00
{
2007-03-29 22:31:56 +00:00
nua_respond ( nh , SIP_200_OK ,
2006-10-12 00:59:09 +00:00
//SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
//SOATAG_AUDIO_AUX("cn telephone-event"),
//NUTAG_INCLUDE_EXTRA_SDP(1),
TAG_END ( ) ) ;
}
2006-09-30 00:00:07 +00:00
static void sip_r_register ( int status ,
char const * phrase ,
2007-03-30 00:13:31 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] )
2006-11-19 20:30:17 +00:00
{
2007-03-19 21:09:53 +00:00
if ( sofia_private & & sofia_private - > gateway ) {
switch ( status ) {
case 200 :
if ( sip & & sip - > sip_contact & & sip - > sip_contact - > m_expires ) {
char * new_expires = ( char * ) sip - > sip_contact - > m_expires ;
2007-03-29 22:31:56 +00:00
uint32_t expi = ( uint32_t ) atoi ( new_expires ) ;
2007-03-19 21:09:53 +00:00
if ( expi ! = sofia_private - > gateway - > freq ) {
sofia_private - > gateway - > freq = expi ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE ,
2007-03-30 00:13:31 +00:00
" Changing expire time to %d by request of proxy %s \n " , expi , sofia_private - > gateway - > register_proxy ) ;
2007-03-19 21:09:53 +00:00
}
}
sofia_private - > gateway - > state = REG_STATE_REGISTER ;
break ;
case 100 :
break ;
default :
sofia_private - > gateway - > state = REG_STATE_FAILED ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Registration Failed with status %d \n " , status ) ;
break ;
2006-11-19 20:30:17 +00:00
}
}
}
static void sip_r_challenge ( int status ,
2007-03-29 22:31:56 +00:00
char const * phrase ,
2007-03-30 00:13:31 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , switch_core_session_t * session , sip_t const * sip , tagi_t tags [ ] )
2006-09-30 00:00:07 +00:00
{
2007-03-19 21:09:53 +00:00
outbound_reg_t * gateway = NULL ;
2006-09-30 00:00:07 +00:00
sip_www_authenticate_t const * authenticate = NULL ;
2007-03-29 22:31:56 +00:00
char const * realm = NULL ;
2006-11-18 16:35:03 +00:00
char * p = NULL , * duprealm = NULL , * qrealm = NULL ;
2006-10-25 15:46:42 +00:00
char const * scheme = NULL ;
2007-02-14 03:24:20 +00:00
int indexnum ;
2006-10-25 15:46:42 +00:00
char * cur ;
2006-11-19 20:08:16 +00:00
char authentication [ 256 ] = " " ;
int ss_state ;
2007-03-29 22:31:56 +00:00
2006-10-03 04:08:30 +00:00
if ( session ) {
private_object_t * tech_pvt ;
if ( ( tech_pvt = switch_core_session_get_private ( session ) ) & & switch_test_flag ( tech_pvt , TFLAG_REFER ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " received reply from refer \n " ) ;
return ;
}
}
2006-10-21 22:54:55 +00:00
2006-11-19 20:08:16 +00:00
2006-11-19 20:30:17 +00:00
if ( sip - > sip_www_authenticate ) {
authenticate = sip - > sip_www_authenticate ;
} else if ( sip - > sip_proxy_authenticate ) {
authenticate = sip - > sip_proxy_authenticate ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Missing Authenticate Header! \n " ) ;
return ;
}
scheme = ( char const * ) authenticate - > au_scheme ;
if ( authenticate - > au_params ) {
2007-03-29 22:31:56 +00:00
for ( indexnum = 0 ; ( cur = ( char * ) authenticate - > au_params [ indexnum ] ) ; indexnum + + ) {
2006-11-19 20:30:17 +00:00
if ( ( realm = strstr ( cur , " realm= " ) ) ) {
realm + = 6 ;
break ;
2006-10-25 15:46:42 +00:00
}
}
2006-11-19 20:30:17 +00:00
}
2006-10-25 15:46:42 +00:00
2006-11-19 20:30:17 +00:00
if ( ! ( scheme & & realm ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " No scheme and realm! \n " ) ;
return ;
}
2006-10-25 17:00:57 +00:00
2006-11-19 20:30:17 +00:00
if ( profile ) {
2007-03-19 21:09:53 +00:00
outbound_reg_t * gateway_ptr ;
2006-11-19 19:51:40 +00:00
2006-11-19 20:30:17 +00:00
if ( ( duprealm = strdup ( realm ) ) ) {
qrealm = duprealm ;
2007-03-29 22:31:56 +00:00
while ( * qrealm & & * qrealm = = ' " ' ) {
2006-11-19 20:30:17 +00:00
qrealm + + ;
}
2006-11-19 20:08:16 +00:00
2006-11-19 20:30:17 +00:00
if ( ( p = strchr ( qrealm , ' " ' ) ) ) {
* p = ' \0 ' ;
}
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( sip - > sip_from ) {
2007-03-29 22:31:56 +00:00
char * from_key = switch_mprintf ( " sip:%s@%s " ,
2007-03-19 21:09:53 +00:00
( char * ) sip - > sip_from - > a_url - > url_user ,
( char * ) sip - > sip_from - > a_url - > url_host ) ;
if ( ! ( gateway = find_gateway ( from_key ) ) ) {
gateway = find_gateway ( qrealm ) ;
2007-03-29 22:31:56 +00:00
}
2007-03-19 21:09:53 +00:00
switch_safe_free ( from_key ) ;
}
2006-11-17 18:22:32 +00:00
2007-03-19 21:09:53 +00:00
if ( ! gateway ) {
for ( gateway_ptr = profile - > gateways ; gateway_ptr ; gateway_ptr = gateway_ptr - > next ) {
2007-03-29 22:31:56 +00:00
if ( scheme & & qrealm & & ! strcasecmp ( gateway_ptr - > register_scheme , scheme )
& & ! strcasecmp ( gateway_ptr - > register_realm , qrealm ) ) {
2007-03-19 21:09:53 +00:00
gateway = gateway_ptr ;
break ;
}
2006-11-19 19:51:40 +00:00
}
}
2007-03-19 21:09:53 +00:00
if ( ! gateway ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " No Match for Scheme [%s] Realm [%s] \n " , scheme , qrealm ) ;
2006-11-21 19:30:39 +00:00
return ;
2006-11-19 20:30:17 +00:00
}
switch_safe_free ( duprealm ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Memory Error! \n " ) ;
return ;
2006-10-25 15:46:42 +00:00
}
2006-11-19 20:30:17 +00:00
}
2007-03-29 22:31:56 +00:00
2007-03-30 00:13:31 +00:00
snprintf ( authentication , sizeof ( authentication ) , " %s:%s:%s:%s " , scheme , realm , gateway - > register_username , gateway - > register_password ) ;
2007-03-29 22:31:56 +00:00
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Authenticating '%s' with '%s'. \n " , profile - > username , authentication ) ;
2007-03-29 22:31:56 +00:00
2006-11-19 20:30:17 +00:00
ss_state = nua_callstate_authenticating ;
2007-03-29 22:31:56 +00:00
tl_gets ( tags , NUTAG_CALLSTATE_REF ( ss_state ) , SIPTAG_WWW_AUTHENTICATE_REF ( authenticate ) , TAG_END ( ) ) ;
2007-03-19 21:09:53 +00:00
nua_authenticate ( nh , SIPTAG_EXPIRES_STR ( gateway - > expires_str ) , NUTAG_AUTH ( authentication ) , TAG_END ( ) ) ;
2007-03-29 22:31:56 +00:00
2006-09-30 00:00:07 +00:00
}
static void event_callback ( nua_event_t event ,
int status ,
char const * phrase ,
2007-03-30 00:13:31 +00:00
nua_t * nua , sofia_profile_t * profile , nua_handle_t * nh , sofia_private_t * sofia_private , sip_t const * sip , tagi_t tags [ ] )
2006-08-25 23:55:59 +00:00
{
2006-09-29 18:12:31 +00:00
struct private_object * tech_pvt = NULL ;
auth_res_t auth_res = AUTH_FORBIDDEN ;
2006-12-28 19:38:35 +00:00
switch_core_session_t * session = NULL ;
2007-03-29 22:31:56 +00:00
switch_channel_t * channel = NULL ;
if ( sofia_private ) {
if ( ! switch_strlen_zero ( sofia_private - > uuid ) ) {
if ( ( session = switch_core_session_locate ( sofia_private - > uuid ) ) ) {
tech_pvt = switch_core_session_get_private ( session ) ;
channel = switch_core_session_get_channel ( tech_pvt - > session ) ;
if ( switch_channel_test_flag ( channel , CF_NOMEDIA ) ) {
switch_set_flag ( tech_pvt , TFLAG_NOMEDIA ) ;
}
if ( ! tech_pvt - > call_id & & sip & & sip - > sip_call_id & & sip - > sip_call_id - > i_id ) {
tech_pvt - > call_id = switch_core_session_strdup ( session , ( char * ) sip - > sip_call_id - > i_id ) ;
switch_channel_set_variable ( channel , " sip_call_id " , tech_pvt - > call_id ) ;
}
} else {
/* too late */
return ;
}
}
}
2006-09-29 18:12:31 +00:00
2006-12-29 00:57:08 +00:00
2006-10-20 06:17:00 +00:00
if ( status ! = 100 & & status ! = 200 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " event [%s] status [%d][%s] session: %s \n " ,
2007-03-29 22:31:56 +00:00
nua_event_name ( event ) , status , phrase , session ? switch_channel_get_name ( channel ) : " n/a " ) ;
2006-10-20 06:17:00 +00:00
}
2006-09-29 18:12:31 +00:00
if ( ( profile - > pflags & PFLAG_AUTH_ALL ) & & tech_pvt & & tech_pvt - > key & & sip ) {
sip_authorization_t const * authorization = NULL ;
2007-03-29 22:31:56 +00:00
if ( sip - > sip_authorization ) {
2006-09-29 18:12:31 +00:00
authorization = sip - > sip_authorization ;
} else if ( sip - > sip_proxy_authorization ) {
authorization = sip - > sip_proxy_authorization ;
}
if ( authorization ) {
2007-03-30 00:13:31 +00:00
auth_res = parse_auth ( profile , authorization , ( char * ) sip - > sip_request - > rq_method_name , tech_pvt - > key , strlen ( tech_pvt - > key ) ) ;
2006-09-29 18:12:31 +00:00
}
if ( auth_res ! = AUTH_OK ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
nua_respond ( nh , SIP_401_UNAUTHORIZED , TAG_END ( ) ) ;
2006-10-09 14:47:36 +00:00
goto done ;
2006-09-29 18:12:31 +00:00
}
2006-11-25 16:52:35 +00:00
2006-12-29 00:57:08 +00:00
if ( channel ) {
2006-11-25 16:52:35 +00:00
switch_channel_set_variable ( channel , " sip_authorized " , " true " ) ;
}
2006-09-16 00:43:58 +00:00
}
2006-11-19 20:30:17 +00:00
2006-12-13 22:58:32 +00:00
if ( sip & & ( status = = 401 | | status = = 407 ) ) {
2006-12-28 19:38:35 +00:00
sip_r_challenge ( status , phrase , nua , profile , nh , session , sip , tags ) ;
2006-11-19 20:30:17 +00:00
goto done ;
}
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
switch ( event ) {
2007-03-29 22:31:56 +00:00
case nua_r_shutdown :
case nua_r_get_params :
2006-09-30 00:00:07 +00:00
case nua_r_invite :
2007-03-29 22:31:56 +00:00
case nua_r_unregister :
case nua_r_options :
2006-12-31 19:54:16 +00:00
case nua_i_fork :
case nua_r_info :
2007-03-29 22:31:56 +00:00
case nua_r_bye :
2006-12-31 19:54:16 +00:00
case nua_i_bye :
case nua_r_unsubscribe :
case nua_r_publish :
case nua_r_message :
case nua_r_notify :
2007-03-29 22:31:56 +00:00
case nua_i_notify :
2006-12-31 19:54:16 +00:00
case nua_i_cancel :
case nua_i_error :
case nua_i_active :
case nua_i_ack :
case nua_i_terminated :
case nua_r_set_params :
2007-03-29 22:31:56 +00:00
break ;
2006-08-25 23:55:59 +00:00
case nua_r_register :
2006-09-30 00:00:07 +00:00
sip_r_register ( status , phrase , nua , profile , nh , sofia_private , sip , tags ) ;
2006-08-25 23:55:59 +00:00
break ;
2006-10-12 00:59:09 +00:00
case nua_i_options :
sip_i_options ( status , phrase , nua , profile , nh , sofia_private , sip , tags ) ;
break ;
2007-03-29 22:31:56 +00:00
case nua_i_invite :
if ( ! session ) {
sip_i_invite ( nua , profile , nh , sofia_private , sip , tags ) ;
}
2006-08-25 23:55:59 +00:00
break ;
2006-10-15 05:10:34 +00:00
case nua_i_publish :
sip_i_publish ( nua , profile , nh , sofia_private , sip , tags ) ;
break ;
2007-03-29 22:31:56 +00:00
case nua_i_register :
sip_i_register ( nua , profile , nh , sofia_private , sip , tags ) ;
break ;
2006-08-25 23:55:59 +00:00
case nua_i_prack :
break ;
case nua_i_state :
2006-09-30 00:00:07 +00:00
sip_i_state ( status , phrase , nua , profile , nh , sofia_private , sip , tags ) ;
2006-08-25 23:55:59 +00:00
break ;
case nua_i_message :
2006-10-12 00:59:09 +00:00
sip_i_message ( status , phrase , nua , profile , nh , sofia_private , sip , tags ) ;
2006-08-25 23:55:59 +00:00
break ;
case nua_i_info :
2006-10-24 22:11:25 +00:00
sip_i_info ( nua , profile , nh , session , sip , tags ) ;
2006-08-25 23:55:59 +00:00
break ;
case nua_r_refer :
break ;
case nua_i_refer :
2007-03-29 22:31:56 +00:00
if ( session ) {
sip_i_refer ( nua , profile , nh , session , sip , tags ) ;
}
2006-08-25 23:55:59 +00:00
break ;
2007-03-29 22:31:56 +00:00
case nua_r_subscribe :
2006-10-12 00:59:09 +00:00
sip_r_subscribe ( status , phrase , nua , profile , nh , sofia_private , sip , tags ) ;
break ;
case nua_i_subscribe :
sip_i_subscribe ( status , phrase , nua , profile , nh , sofia_private , sip , tags ) ;
2006-08-25 23:55:59 +00:00
break ;
default :
2006-12-31 19:54:16 +00:00
if ( status > 100 ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s: unknown event %d: %03d %s \n " , nua_event_name ( event ) , event , status , phrase ) ;
2007-03-29 22:31:56 +00:00
} else {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s: unknown event %d \n " , nua_event_name ( event ) , event ) ;
2007-03-29 22:31:56 +00:00
}
2006-08-25 23:55:59 +00:00
break ;
}
2006-09-16 00:43:58 +00:00
2007-03-29 22:31:56 +00:00
done :
2006-10-09 14:47:36 +00:00
2006-09-16 00:43:58 +00:00
if ( session ) {
switch_core_session_rwunlock ( session ) ;
}
2006-08-25 23:55:59 +00:00
}
2006-10-25 15:46:42 +00:00
2007-03-29 22:31:56 +00:00
static void unreg ( sofia_profile_t * profile )
2006-10-25 15:46:42 +00:00
{
2007-03-19 21:09:53 +00:00
outbound_reg_t * gateway_ptr ;
2007-03-29 22:31:56 +00:00
for ( gateway_ptr = profile - > gateways ; gateway_ptr ; gateway_ptr = gateway_ptr - > next ) {
if ( gateway_ptr - > sofia_private ) {
free ( gateway_ptr - > sofia_private ) ;
nua_handle_bind ( gateway_ptr - > nh , NULL ) ;
gateway_ptr - > sofia_private = NULL ;
}
2007-03-19 21:09:53 +00:00
nua_handle_destroy ( gateway_ptr - > nh ) ;
2006-10-25 15:46:42 +00:00
}
}
2007-03-29 22:31:56 +00:00
static void check_gateway ( sofia_profile_t * profile , time_t now )
2006-09-30 00:00:07 +00:00
{
2007-03-19 21:09:53 +00:00
outbound_reg_t * gateway_ptr ;
for ( gateway_ptr = profile - > gateways ; gateway_ptr ; gateway_ptr = gateway_ptr - > next ) {
2006-09-30 00:00:07 +00:00
int ss_state = nua_callstate_authenticating ;
2007-03-19 21:09:53 +00:00
reg_state_t ostate = gateway_ptr - > state ;
2006-09-30 00:00:07 +00:00
2007-03-29 22:31:56 +00:00
switch ( ostate ) {
2006-09-30 00:00:07 +00:00
case REG_STATE_REGISTER :
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " registered %s \n " , gateway_ptr - > name ) ;
2007-03-19 21:09:53 +00:00
gateway_ptr - > expires = now + gateway_ptr - > freq ;
gateway_ptr - > state = REG_STATE_REGED ;
2006-09-30 00:00:07 +00:00
break ;
case REG_STATE_UNREGED :
2007-03-19 21:09:53 +00:00
if ( ( gateway_ptr - > nh = nua_handle ( gateway_ptr - > profile - > nua , NULL ,
2007-03-29 22:31:56 +00:00
NUTAG_URL ( gateway_ptr - > register_proxy ) ,
SIPTAG_TO_STR ( gateway_ptr - > register_to ) ,
2007-03-30 00:13:31 +00:00
NUTAG_CALLSTATE_REF ( ss_state ) , SIPTAG_FROM_STR ( gateway_ptr - > register_from ) , TAG_END ( ) ) ) ) {
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " registering %s \n " , gateway_ptr - > name ) ;
if ( ! ( gateway_ptr - > sofia_private = malloc ( sizeof ( * gateway_ptr - > sofia_private ) ) ) ) {
abort ( ) ;
}
memset ( gateway_ptr - > sofia_private , 0 , sizeof ( * gateway_ptr - > sofia_private ) ) ;
2007-03-19 21:09:53 +00:00
gateway_ptr - > sofia_private - > gateway = gateway_ptr ;
nua_handle_bind ( gateway_ptr - > nh , gateway_ptr - > sofia_private ) ;
nua_register ( gateway_ptr - > nh ,
SIPTAG_FROM_STR ( gateway_ptr - > register_from ) ,
SIPTAG_CONTACT_STR ( gateway_ptr - > register_contact ) ,
SIPTAG_EXPIRES_STR ( gateway_ptr - > expires_str ) ,
NUTAG_REGISTRAR ( gateway_ptr - > register_proxy ) ,
2007-03-30 00:13:31 +00:00
NUTAG_OUTBOUND ( " no-options-keepalive " ) , NUTAG_OUTBOUND ( " no-validate " ) , NUTAG_KEEPALIVE ( 0 ) , TAG_NULL ( ) ) ;
2007-03-19 21:09:53 +00:00
gateway_ptr - > retry = now + 10 ;
gateway_ptr - > state = REG_STATE_TRYING ;
2006-11-17 00:13:36 +00:00
} else {
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error registering %s \n " , gateway_ptr - > name ) ;
2007-03-19 21:09:53 +00:00
gateway_ptr - > state = REG_STATE_FAILED ;
2006-09-30 00:00:07 +00:00
}
break ;
2006-09-30 16:30:29 +00:00
case REG_STATE_TRYING :
2007-03-19 21:09:53 +00:00
if ( gateway_ptr - > retry & & now > = gateway_ptr - > retry ) {
gateway_ptr - > state = REG_STATE_UNREGED ;
gateway_ptr - > retry = 0 ;
2006-09-30 00:00:07 +00:00
}
2006-09-30 16:30:29 +00:00
break ;
default :
2007-03-20 23:09:35 +00:00
if ( now > = gateway_ptr - > expires ) {
2007-03-19 21:09:53 +00:00
gateway_ptr - > state = REG_STATE_UNREGED ;
2006-09-30 00:00:07 +00:00
}
break ;
}
}
}
# define IREG_SECONDS 30
2007-03-19 21:09:53 +00:00
# define GATEWAY_SECONDS 1
2007-03-30 00:13:31 +00:00
static void * SWITCH_THREAD_FUNC profile_thread_run ( switch_thread_t * thread , void * obj )
2006-08-25 23:55:59 +00:00
{
sofia_profile_t * profile = ( sofia_profile_t * ) obj ;
switch_memory_pool_t * pool ;
sip_alias_node_t * node ;
2006-09-30 00:00:07 +00:00
uint32_t ireg_loops = 0 ;
2007-03-19 21:09:53 +00:00
uint32_t gateway_loops = 0 ;
2006-09-27 04:34:19 +00:00
switch_core_db_t * db ;
2006-10-05 14:24:25 +00:00
switch_event_t * s_event ;
2006-09-30 00:00:07 +00:00
2006-08-25 23:55:59 +00:00
profile - > s_root = su_root_create ( NULL ) ;
2006-10-15 05:10:34 +00:00
profile - > home = su_home_new ( sizeof ( * profile - > home ) ) ;
2007-03-29 22:31:56 +00:00
profile - > nua = nua_create ( profile - > s_root , /* Event loop */
event_callback , /* Callback for processing events */
profile , /* Additional data to pass to callback */
NUTAG_URL ( profile - > bindurl ) , NTATAG_UDP_MTU ( 65536 ) , TAG_END ( ) ) ; /* Last tag should always finish the sequence */
2006-08-25 23:55:59 +00:00
2006-08-28 23:50:10 +00:00
nua_set_params ( profile - > nua ,
2007-03-29 22:31:56 +00:00
//NUTAG_EARLY_MEDIA(1),
2006-08-28 23:50:10 +00:00
NUTAG_AUTOANSWER ( 0 ) ,
2006-08-29 01:27:23 +00:00
NUTAG_AUTOALERT ( 0 ) ,
2006-09-27 03:44:14 +00:00
NUTAG_ALLOW ( " REGISTER " ) ,
2006-10-03 04:08:30 +00:00
NUTAG_ALLOW ( " REFER " ) ,
2006-10-24 22:11:25 +00:00
NUTAG_ALLOW ( " INFO " ) ,
2006-10-12 00:59:09 +00:00
TAG_IF ( ( profile - > pflags & PFLAG_PRESENCE ) , NUTAG_ALLOW ( " PUBLISH " ) ) ,
2006-10-23 20:28:55 +00:00
TAG_IF ( ( profile - > pflags & PFLAG_PRESENCE ) , NUTAG_ALLOW ( " NOTIFY " ) ) ,
TAG_IF ( ( profile - > pflags & PFLAG_PRESENCE ) , NUTAG_ALLOW ( " SUBSCRIBE " ) ) ,
2006-10-12 00:59:09 +00:00
TAG_IF ( ( profile - > pflags & PFLAG_PRESENCE ) , NUTAG_ENABLEMESSAGE ( 1 ) ) ,
2006-12-03 03:19:35 +00:00
TAG_IF ( ( profile - > pflags & PFLAG_PRESENCE ) , NUTAG_ALLOW_EVENTS ( " presence " ) ) ,
TAG_IF ( ( profile - > pflags & PFLAG_PRESENCE ) , NUTAG_ALLOW_EVENTS ( " presence.winfo " ) ) ,
2007-03-29 22:31:56 +00:00
SIPTAG_SUPPORTED_STR ( " 100rel, precondition " ) , SIPTAG_USER_AGENT_STR ( SOFIA_USER_AGENT ) , TAG_END ( ) ) ;
2006-08-28 23:50:10 +00:00
2006-08-25 23:55:59 +00:00
for ( node = profile - > aliases ; node ; node = node - > next ) {
2007-03-29 22:31:56 +00:00
node - > nua = nua_create ( profile - > s_root , /* Event loop */
event_callback , /* Callback for processing events */
profile , /* Additional data to pass to callback */
NUTAG_URL ( node - > url ) , TAG_END ( ) ) ; /* Last tag should always finish the sequence */
2006-08-25 23:55:59 +00:00
2006-08-28 23:50:10 +00:00
nua_set_params ( node - > nua ,
2007-03-29 22:31:56 +00:00
NUTAG_EARLY_MEDIA ( 1 ) ,
2006-08-28 23:50:10 +00:00
NUTAG_AUTOANSWER ( 0 ) ,
2006-09-29 01:07:51 +00:00
NUTAG_AUTOALERT ( 0 ) ,
2006-09-27 03:44:14 +00:00
NUTAG_ALLOW ( " REGISTER " ) ,
2006-10-10 03:19:59 +00:00
NUTAG_ALLOW ( " REFER " ) ,
2006-10-24 22:11:25 +00:00
NUTAG_ALLOW ( " INFO " ) ,
2006-10-12 00:59:09 +00:00
TAG_IF ( ( profile - > pflags & PFLAG_PRESENCE ) , NUTAG_ALLOW ( " PUBLISH " ) ) ,
TAG_IF ( ( profile - > pflags & PFLAG_PRESENCE ) , NUTAG_ENABLEMESSAGE ( 1 ) ) ,
2007-03-30 00:13:31 +00:00
SIPTAG_SUPPORTED_STR ( " 100rel, precondition " ) , SIPTAG_USER_AGENT_STR ( SOFIA_USER_AGENT ) , TAG_END ( ) ) ;
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
}
2006-09-27 03:44:14 +00:00
2006-09-27 04:34:19 +00:00
if ( ( db = switch_core_db_open_file ( profile - > dbname ) ) ) {
2006-10-15 05:10:34 +00:00
switch_core_db_test_reactive ( db , " select contact from sip_registrations " , reg_sql ) ;
switch_core_db_test_reactive ( db , " select contact from sip_subscriptions " , sub_sql ) ;
2006-09-28 21:21:44 +00:00
switch_core_db_test_reactive ( db , " select * from sip_authentication " , auth_sql ) ;
2006-09-27 03:44:14 +00:00
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Cannot Open SQL Database! \n " ) ;
return NULL ;
}
2006-12-28 01:08:06 +00:00
2006-09-27 03:44:14 +00:00
2006-09-30 00:00:07 +00:00
switch_mutex_init ( & profile - > ireg_mutex , SWITCH_MUTEX_NESTED , profile - > pool ) ;
2007-03-19 21:09:53 +00:00
switch_mutex_init ( & profile - > gateway_mutex , SWITCH_MUTEX_NESTED , profile - > pool ) ;
2006-09-27 03:44:14 +00:00
2006-09-30 00:00:07 +00:00
ireg_loops = IREG_SECONDS ;
2007-03-19 21:09:53 +00:00
gateway_loops = GATEWAY_SECONDS ;
2006-09-27 03:44:14 +00:00
2006-10-05 14:24:25 +00:00
if ( switch_event_create ( & s_event , SWITCH_EVENT_PUBLISH ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " service " , " _sip._udp " ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " port " , " %d " , profile - > sip_port ) ;
switch_event_fire ( & s_event ) ;
}
2006-10-12 00:59:09 +00:00
if ( switch_event_create ( & s_event , SWITCH_EVENT_PUBLISH ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " service " , " _sip._tcp " ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " port " , " %d " , profile - > sip_port ) ;
switch_event_fire ( & s_event ) ;
}
if ( switch_event_create ( & s_event , SWITCH_EVENT_PUBLISH ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " service " , " _sip._sctp " ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " port " , " %d " , profile - > sip_port ) ;
switch_event_fire ( & s_event ) ;
}
2007-03-19 21:09:53 +00:00
add_profile ( profile - > name , profile ) ;
2006-10-18 22:57:35 +00:00
2006-10-20 06:17:00 +00:00
if ( profile - > pflags & PFLAG_PRESENCE ) {
2006-10-20 22:11:26 +00:00
establish_presence ( profile ) ;
2006-10-20 06:17:00 +00:00
}
2006-10-18 22:57:35 +00:00
2007-03-29 22:31:56 +00:00
while ( globals . running = = 1 ) {
2006-09-30 00:00:07 +00:00
if ( + + ireg_loops > = IREG_SECONDS ) {
2006-12-28 01:08:06 +00:00
check_expire ( db , profile , time ( NULL ) ) ;
2006-09-30 00:00:07 +00:00
ireg_loops = 0 ;
}
2007-03-19 21:09:53 +00:00
if ( + + gateway_loops > = GATEWAY_SECONDS ) {
check_gateway ( profile , time ( NULL ) ) ;
gateway_loops = 0 ;
2006-09-27 03:44:14 +00:00
}
su_root_step ( profile - > s_root , 1000 ) ;
}
2006-10-12 00:59:09 +00:00
2006-12-28 01:08:06 +00:00
switch_core_db_close ( db ) ;
2006-10-25 15:46:42 +00:00
unreg ( profile ) ;
2006-11-20 21:45:00 +00:00
su_home_unref ( profile - > home ) ;
2007-03-29 22:31:56 +00:00
2006-10-15 05:10:34 +00:00
2006-10-05 14:24:25 +00:00
if ( switch_event_create ( & s_event , SWITCH_EVENT_UNPUBLISH ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " service " , " _sip._udp " ) ;
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " port " , " %d " , profile - > sip_port ) ;
switch_event_fire ( & s_event ) ;
}
2006-08-25 23:55:59 +00:00
su_root_destroy ( profile - > s_root ) ;
pool = profile - > pool ;
switch_core_destroy_memory_pool ( & pool ) ;
2006-09-27 03:44:14 +00:00
switch_mutex_lock ( globals . mutex ) ;
globals . running = 0 ;
switch_mutex_unlock ( globals . mutex ) ;
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
return NULL ;
}
2007-03-29 22:31:56 +00:00
static void launch_profile_thread ( sofia_profile_t * profile )
2006-08-25 23:55:59 +00:00
{
switch_thread_t * thread ;
switch_threadattr_t * thd_attr = NULL ;
2007-03-29 22:31:56 +00:00
2006-08-25 23:55:59 +00:00
switch_threadattr_create ( & thd_attr , profile - > pool ) ;
switch_threadattr_detach_set ( thd_attr , 1 ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
switch_thread_create ( & thread , thd_attr , profile_thread_run , profile , profile - > pool ) ;
}
static switch_status_t config_sofia ( int reload )
{
char * cf = " sofia.conf " ;
2007-03-19 21:09:53 +00:00
switch_xml_t cfg , xml = NULL , xprofile , param , settings , profiles , gateway_tag , gateways_tag ;
2006-08-25 23:55:59 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2006-09-30 00:00:07 +00:00
sofia_profile_t * profile = NULL ;
char url [ 512 ] = " " ;
2006-10-12 00:59:09 +00:00
switch_mutex_lock ( globals . mutex ) ;
globals . running = 1 ;
switch_mutex_unlock ( globals . mutex ) ;
2006-08-25 23:55:59 +00:00
if ( ! ( xml = switch_xml_open_cfg ( cf , & cfg , NULL ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " open of %s failed \n " , cf ) ;
status = SWITCH_STATUS_FALSE ;
goto done ;
}
2006-10-09 17:11:39 +00:00
if ( ( settings = switch_xml_child ( cfg , " global_settings " ) ) ) {
for ( param = switch_xml_child ( settings , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " log-level " ) ) {
su_log_set_level ( NULL , atoi ( val ) ) ;
2006-10-15 05:20:49 +00:00
} else if ( ! strcasecmp ( var , " log-level-trace " ) ) {
su_log_set_level ( tport_log , atoi ( val ) ) ;
2006-10-09 17:11:39 +00:00
}
}
}
2006-09-30 00:00:07 +00:00
if ( ( profiles = switch_xml_child ( cfg , " profiles " ) ) ) {
for ( xprofile = switch_xml_child ( profiles , " profile " ) ; xprofile ; xprofile = xprofile - > next ) {
if ( ! ( settings = switch_xml_child ( xprofile , " settings " ) ) ) {
2007-03-09 23:51:52 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " No Settings, check the new config! \n " ) ;
2006-09-30 00:00:07 +00:00
} else {
char * xprofilename = ( char * ) switch_xml_attr_soft ( xprofile , " name " ) ;
switch_memory_pool_t * pool = NULL ;
2006-08-25 23:55:59 +00:00
2007-03-29 22:31:56 +00:00
2006-09-30 00:00:07 +00:00
/* Setup the pool */
if ( ( status = switch_core_new_memory_pool ( & pool ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Memory Error! \n " ) ;
goto done ;
}
2006-08-25 23:55:59 +00:00
2006-09-30 00:00:07 +00:00
if ( ! ( profile = ( sofia_profile_t * ) switch_core_alloc ( pool , sizeof ( * profile ) ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Memory Error! \n " ) ;
goto done ;
}
2006-08-25 23:55:59 +00:00
2006-09-30 00:00:07 +00:00
if ( ! xprofilename ) {
xprofilename = " unnamed " ;
}
2007-03-29 22:31:56 +00:00
2006-09-30 00:00:07 +00:00
profile - > pool = pool ;
profile - > name = switch_core_strdup ( profile - > pool , xprofilename ) ;
snprintf ( url , sizeof ( url ) , " sofia_reg_%s " , xprofilename ) ;
profile - > dbname = switch_core_strdup ( profile - > pool , url ) ;
2006-10-18 22:57:35 +00:00
switch_core_hash_init ( & profile - > chat_hash , profile - > pool ) ;
2006-09-30 00:00:07 +00:00
2007-03-29 22:31:56 +00:00
profile - > dtmf_duration = 100 ;
2006-09-30 00:00:07 +00:00
profile - > codec_ms = 20 ;
for ( param = switch_xml_child ( settings , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " debug " ) ) {
profile - > debug = atoi ( val ) ;
} else if ( ! strcasecmp ( var , " use-rtp-timer " ) & & switch_true ( val ) ) {
switch_set_flag ( profile , TFLAG_TIMER ) ;
2006-12-29 00:57:08 +00:00
} else if ( ! strcasecmp ( var , " inbound-no-media " ) & & switch_true ( val ) ) {
switch_set_flag ( profile , TFLAG_INB_NOMEDIA ) ;
2007-01-20 18:51:57 +00:00
} else if ( ! strcasecmp ( var , " inbound-late-negotiation " ) & & switch_true ( val ) ) {
switch_set_flag ( profile , TFLAG_LATE_NEGOTIATION ) ;
2006-09-30 00:00:07 +00:00
} else if ( ! strcasecmp ( var , " rfc2833-pt " ) ) {
profile - > te = ( switch_payload_t ) atoi ( val ) ;
2007-03-07 18:34:22 +00:00
} else if ( ! strcasecmp ( var , " cng-pt " ) ) {
profile - > cng_pt = ( switch_payload_t ) atoi ( val ) ;
2006-09-30 00:00:07 +00:00
} else if ( ! strcasecmp ( var , " sip-port " ) ) {
profile - > sip_port = atoi ( val ) ;
} else if ( ! strcasecmp ( var , " vad " ) ) {
if ( ! strcasecmp ( val , " in " ) ) {
switch_set_flag ( profile , TFLAG_VAD_IN ) ;
} else if ( ! strcasecmp ( val , " out " ) ) {
switch_set_flag ( profile , TFLAG_VAD_OUT ) ;
} else if ( ! strcasecmp ( val , " both " ) ) {
switch_set_flag ( profile , TFLAG_VAD_IN ) ;
switch_set_flag ( profile , TFLAG_VAD_OUT ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invald option %s for VAD \n " , val ) ;
}
} else if ( ! strcasecmp ( var , " ext-rtp-ip " ) ) {
2007-03-30 00:13:31 +00:00
profile - > extrtpip = switch_core_strdup ( profile - > pool , strcasecmp ( val , " auto " ) ? val : globals . guess_ip ) ;
2006-09-30 00:00:07 +00:00
} else if ( ! strcasecmp ( var , " rtp-ip " ) ) {
2007-03-30 00:13:31 +00:00
profile - > rtpip = switch_core_strdup ( profile - > pool , strcasecmp ( val , " auto " ) ? val : globals . guess_ip ) ;
2006-09-30 00:00:07 +00:00
} else if ( ! strcasecmp ( var , " sip-ip " ) ) {
2007-03-30 00:13:31 +00:00
profile - > sipip = switch_core_strdup ( profile - > pool , strcasecmp ( val , " auto " ) ? val : globals . guess_ip ) ;
2007-03-08 20:05:09 +00:00
} else if ( ! strcasecmp ( var , " ext-sip-ip " ) ) {
if ( ! strcasecmp ( val , " auto " ) ) {
profile - > extsipip = switch_core_strdup ( profile - > pool , globals . guess_ip ) ;
} else {
char * ip = NULL ;
switch_port_t port = 0 ;
2007-03-29 22:31:56 +00:00
if ( sofia_ext_address_lookup ( & ip , & port , val , profile - > pool ) = = SWITCH_STATUS_SUCCESS ) {
2007-03-08 20:05:09 +00:00
if ( ip ) {
profile - > extsipip = switch_core_strdup ( profile - > pool , ip ) ;
}
}
}
2006-09-30 00:00:07 +00:00
} else if ( ! strcasecmp ( var , " sip-domain " ) ) {
profile - > sipdomain = switch_core_strdup ( profile - > pool , val ) ;
} else if ( ! strcasecmp ( var , " rtp-timer-name " ) ) {
profile - > timer_name = switch_core_strdup ( profile - > pool , val ) ;
2006-10-12 00:59:09 +00:00
} else if ( ! strcasecmp ( var , " manage-presence " ) ) {
if ( switch_true ( val ) ) {
profile - > pflags | = PFLAG_PRESENCE ;
}
2007-01-28 02:38:52 +00:00
} else if ( ! strcasecmp ( var , " pass-rfc2833 " ) ) {
if ( switch_true ( val ) ) {
profile - > pflags | = PFLAG_PASS_RFC2833 ;
}
2007-01-28 17:37:51 +00:00
} else if ( ! strcasecmp ( var , " disable-transcoding " ) ) {
if ( switch_true ( val ) ) {
profile - > pflags | = PFLAG_DISABLE_TRANSCODING ;
}
2006-09-30 00:00:07 +00:00
} else if ( ! strcasecmp ( var , " auth-calls " ) ) {
if ( switch_true ( val ) ) {
profile - > pflags | = PFLAG_AUTH_CALLS ;
}
2007-01-23 22:04:05 +00:00
} else if ( ! strcasecmp ( var , " nonce-ttl " ) ) {
2007-03-29 22:31:56 +00:00
profile - > nonce_ttl = atoi ( val ) ;
2006-09-30 00:00:07 +00:00
} else if ( ! strcasecmp ( var , " accept-blind-reg " ) ) {
if ( switch_true ( val ) ) {
profile - > pflags | = PFLAG_BLIND_REG ;
}
} else if ( ! strcasecmp ( var , " auth-all-packets " ) ) {
if ( switch_true ( val ) ) {
profile - > pflags | = PFLAG_AUTH_ALL ;
}
2006-10-05 14:24:25 +00:00
} else if ( ! strcasecmp ( var , " full-id-in-dialplan " ) ) {
if ( switch_true ( val ) ) {
profile - > pflags | = PFLAG_FULL_ID ;
}
2006-09-30 00:00:07 +00:00
} else if ( ! strcasecmp ( var , " bitpacking " ) ) {
if ( ! strcasecmp ( val , " aal2 " ) ) {
profile - > codec_flags = SWITCH_CODEC_FLAG_AAL2 ;
2007-03-29 22:31:56 +00:00
}
2006-09-30 00:00:07 +00:00
} else if ( ! strcasecmp ( var , " username " ) ) {
profile - > username = switch_core_strdup ( profile - > pool , val ) ;
} else if ( ! strcasecmp ( var , " context " ) ) {
profile - > context = switch_core_strdup ( profile - > pool , val ) ;
} else if ( ! strcasecmp ( var , " alias " ) ) {
sip_alias_node_t * node ;
if ( ( node = switch_core_alloc ( profile - > pool , sizeof ( * node ) ) ) ) {
if ( ( node - > url = switch_core_strdup ( profile - > pool , val ) ) ) {
node - > next = profile - > aliases ;
profile - > aliases = node ;
}
}
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
profile - > dialplan = switch_core_strdup ( profile - > pool , val ) ;
} else if ( ! strcasecmp ( var , " max-calls " ) ) {
profile - > max_calls = atoi ( val ) ;
} else if ( ! strcasecmp ( var , " codec-prefs " ) ) {
profile - > codec_string = switch_core_strdup ( profile - > pool , val ) ;
} else if ( ! strcasecmp ( var , " codec-ms " ) ) {
profile - > codec_ms = atoi ( val ) ;
} else if ( ! strcasecmp ( var , " dtmf-duration " ) ) {
int dur = atoi ( val ) ;
if ( dur > 10 & & dur < 8000 ) {
profile - > dtmf_duration = dur ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Duration out of bounds! \n " ) ;
}
}
}
2006-08-25 23:55:59 +00:00
2007-03-29 22:31:56 +00:00
if ( ! profile - > cng_pt ) {
2007-03-07 20:06:15 +00:00
profile - > cng_pt = SWITCH_RTP_CNG_PAYLOAD ;
2007-03-07 18:34:22 +00:00
}
2007-03-29 22:31:56 +00:00
if ( ! profile - > sipip ) {
profile - > sipip = switch_core_strdup ( profile - > pool , globals . guess_ip ) ;
}
2007-01-29 15:51:38 +00:00
2007-03-29 22:31:56 +00:00
if ( ! profile - > rtpip ) {
profile - > rtpip = switch_core_strdup ( profile - > pool , globals . guess_ip ) ;
}
2007-01-29 15:51:38 +00:00
2007-03-29 22:31:56 +00:00
if ( profile - > nonce_ttl < 60 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Setting nonce TTL to 60 seconds \n " ) ;
profile - > nonce_ttl = 60 ;
}
2007-01-23 22:04:05 +00:00
2006-09-30 00:00:07 +00:00
if ( switch_test_flag ( profile , TFLAG_TIMER ) & & ! profile - > timer_name ) {
2007-03-29 22:31:56 +00:00
profile - > timer_name = switch_core_strdup ( profile - > pool , " soft " ) ;
2006-09-30 00:00:07 +00:00
}
2006-09-07 15:08:40 +00:00
2006-09-30 00:00:07 +00:00
if ( ! profile - > username ) {
profile - > username = switch_core_strdup ( profile - > pool , " FreeSWITCH " ) ;
}
2006-08-25 23:55:59 +00:00
2006-09-30 00:00:07 +00:00
if ( ! profile - > rtpip ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Setting ip to '127.0.0.1' \n " ) ;
profile - > rtpip = switch_core_strdup ( profile - > pool , " 127.0.0.1 " ) ;
2006-08-25 23:55:59 +00:00
}
2006-09-30 00:00:07 +00:00
if ( ! profile - > sip_port ) {
2007-03-19 21:09:53 +00:00
profile - > sip_port = atoi ( SOFIA_DEFAULT_PORT ) ;
2006-09-29 01:07:51 +00:00
}
2006-09-30 00:00:07 +00:00
if ( ! profile - > dialplan ) {
2006-10-03 04:08:30 +00:00
profile - > dialplan = switch_core_strdup ( profile - > pool , " XML " ) ;
2006-09-29 18:12:31 +00:00
}
2006-09-30 00:00:07 +00:00
if ( ! profile - > sipdomain ) {
profile - > sipdomain = switch_core_strdup ( profile - > pool , profile - > sipip ) ;
2006-09-29 18:12:31 +00:00
}
2007-01-15 03:52:39 +00:00
if ( profile - > extsipip ) {
2007-03-30 00:13:31 +00:00
profile - > url = switch_core_sprintf ( profile - > pool , " sip:mod_sofia@%s:%d " , profile - > extsipip , profile - > sip_port ) ;
2007-03-02 01:44:36 +00:00
profile - > bindurl = switch_core_sprintf ( profile - > pool , " %s;maddr=%s " , profile - > url , profile - > sipip ) ;
2007-01-15 03:52:39 +00:00
} else {
2007-03-30 00:13:31 +00:00
profile - > url = switch_core_sprintf ( profile - > pool , " sip:mod_sofia@%s:%d " , profile - > sipip , profile - > sip_port ) ;
2007-01-15 04:32:21 +00:00
profile - > bindurl = profile - > url ;
2007-01-15 03:52:39 +00:00
}
2006-09-30 00:00:07 +00:00
}
if ( profile ) {
2007-03-19 21:09:53 +00:00
if ( ( gateways_tag = switch_xml_child ( xprofile , " registrations " ) ) ) {
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT ,
2007-03-19 21:09:53 +00:00
" The <registrations> syntax has been discontinued, please see the new syntax in the default configuration examples \n " ) ;
}
2006-09-30 00:00:07 +00:00
2007-03-19 21:09:53 +00:00
if ( ( gateways_tag = switch_xml_child ( xprofile , " gateways " ) ) ) {
2007-03-30 00:13:31 +00:00
for ( gateway_tag = switch_xml_child ( gateways_tag , " gateway " ) ; gateway_tag ; gateway_tag = gateway_tag - > next ) {
2007-03-19 21:09:53 +00:00
char * name = ( char * ) switch_xml_attr_soft ( gateway_tag , " name " ) ;
outbound_reg_t * gateway ;
2007-03-29 22:31:56 +00:00
2006-09-30 00:00:07 +00:00
if ( switch_strlen_zero ( name ) ) {
name = " anonymous " ;
}
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( ( gateway = switch_core_alloc ( profile - > pool , sizeof ( * gateway ) ) ) ) {
char * scheme = " Digest " ,
* realm = NULL ,
2007-03-30 00:13:31 +00:00
* username = NULL , * password = NULL , * extension = NULL , * proxy = NULL , * context = " default " , * expire_seconds = " 3600 " ;
2007-03-21 02:48:47 +00:00
gateway - > pool = profile - > pool ;
gateway - > profile = profile ;
gateway - > name = switch_core_strdup ( gateway - > pool , name ) ;
gateway - > freq = 0 ;
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
for ( param = switch_xml_child ( gateway_tag , " param " ) ; param ; param = param - > next ) {
2006-09-30 00:00:07 +00:00
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( ! strcmp ( var , " scheme " ) ) {
scheme = val ;
} else if ( ! strcmp ( var , " realm " ) ) {
realm = val ;
} else if ( ! strcmp ( var , " username " ) ) {
username = val ;
} else if ( ! strcmp ( var , " password " ) ) {
password = val ;
} else if ( ! strcmp ( var , " extension " ) ) {
extension = val ;
} else if ( ! strcmp ( var , " proxy " ) ) {
proxy = val ;
2007-03-20 23:09:35 +00:00
} else if ( ! strcmp ( var , " context " ) ) {
context = val ;
2007-03-19 21:09:53 +00:00
} else if ( ! strcmp ( var , " expire-seconds " ) ) {
expire_seconds = val ;
2006-09-30 00:00:07 +00:00
}
}
2007-03-19 21:09:53 +00:00
if ( switch_strlen_zero ( realm ) ) {
realm = name ;
2006-09-30 00:00:07 +00:00
}
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( switch_strlen_zero ( username ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " ERROR: username param is REQUIRED! \n " ) ;
2007-03-19 21:09:53 +00:00
switch_xml_free ( xml ) ;
goto skip ;
2006-09-30 00:00:07 +00:00
}
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( switch_strlen_zero ( password ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " ERROR: password param is REQUIRED! \n " ) ;
2007-03-19 21:09:53 +00:00
switch_xml_free ( xml ) ;
goto skip ;
2006-09-30 00:00:07 +00:00
}
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( switch_strlen_zero ( extension ) ) {
extension = username ;
2006-09-30 00:00:07 +00:00
}
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( switch_strlen_zero ( proxy ) ) {
proxy = realm ;
2006-09-30 00:00:07 +00:00
}
2007-03-19 21:09:53 +00:00
gateway - > register_scheme = switch_core_strdup ( gateway - > pool , scheme ) ;
2007-03-20 23:09:35 +00:00
gateway - > register_context = switch_core_strdup ( gateway - > pool , context ) ;
2007-03-19 21:09:53 +00:00
gateway - > register_realm = switch_core_strdup ( gateway - > pool , realm ) ;
gateway - > register_username = switch_core_strdup ( gateway - > pool , username ) ;
gateway - > register_password = switch_core_strdup ( gateway - > pool , password ) ;
2007-03-20 16:26:12 +00:00
gateway - > register_from = switch_core_sprintf ( gateway - > pool , " sip:%s@%s " , username , realm ) ;
2007-03-30 00:13:31 +00:00
gateway - > register_contact = switch_core_sprintf ( gateway - > pool , " sip:%s@%s:%d " , extension , profile - > sipip , profile - > sip_port ) ;
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( ! strncasecmp ( proxy , " sip: " , 4 ) ) {
gateway - > register_proxy = switch_core_strdup ( gateway - > pool , proxy ) ;
2007-03-30 00:13:31 +00:00
gateway - > register_to = switch_core_sprintf ( gateway - > pool , " sip:%s@%s " , username , proxy + 4 ) ;
2007-03-19 21:09:53 +00:00
} else {
gateway - > register_proxy = switch_core_sprintf ( gateway - > pool , " sip:%s " , proxy ) ;
gateway - > register_to = switch_core_sprintf ( gateway - > pool , " sip:%s@%s " , username , proxy ) ;
2006-09-30 00:00:07 +00:00
}
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
gateway - > expires_str = switch_core_strdup ( gateway - > pool , expire_seconds ) ;
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( ( gateway - > freq = atoi ( gateway - > expires_str ) ) < 5 ) {
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING ,
2007-03-30 00:13:31 +00:00
" Invalid Freq: %d. Setting Register-Frequency to 3600 \n " , gateway - > freq ) ;
2007-03-29 22:31:56 +00:00
gateway - > freq = 3600 ;
}
gateway - > freq - = 2 ;
2007-01-25 14:56:32 +00:00
2007-03-19 21:09:53 +00:00
gateway - > next = profile - > gateways ;
profile - > gateways = gateway ;
2006-10-18 22:57:35 +00:00
2007-03-19 21:09:53 +00:00
if ( find_gateway ( gateway - > name ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Ignoring duplicate gateway '%s' \n " , gateway - > name ) ;
2007-03-19 21:09:53 +00:00
} else if ( find_gateway ( gateway - > register_from ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Ignoring duplicate uri '%s' \n " , gateway - > register_from ) ;
2007-03-20 23:09:35 +00:00
} else if ( find_gateway ( gateway - > register_contact ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Ignoring duplicate contact '%s' \n " , gateway - > register_from ) ;
2007-03-19 21:09:53 +00:00
} else {
add_gateway ( gateway - > name , gateway ) ;
add_gateway ( gateway - > register_from , gateway ) ;
2007-03-20 23:09:35 +00:00
add_gateway ( gateway - > register_contact , gateway ) ;
2007-03-19 21:09:53 +00:00
}
2006-09-30 00:00:07 +00:00
}
2007-03-19 21:09:53 +00:00
2007-03-29 22:31:56 +00:00
skip :
2007-03-19 21:09:53 +00:00
assert ( gateway_tag ) ;
2006-08-25 23:55:59 +00:00
}
}
2007-01-15 19:00:47 +00:00
if ( profile - > sipip ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Started Profile %s [%s] \n " , profile - > name , url ) ;
2007-01-15 19:00:47 +00:00
launch_profile_thread ( profile ) ;
} else {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Unable to start Profile %s due to no configured sip-ip \n " , profile - > name ) ;
2007-01-15 19:00:47 +00:00
}
2006-09-30 00:00:07 +00:00
profile = NULL ;
}
2006-08-29 01:27:23 +00:00
}
2006-08-25 23:55:59 +00:00
}
2007-03-29 22:31:56 +00:00
done :
2006-08-25 23:55:59 +00:00
if ( xml ) {
switch_xml_free ( xml ) ;
}
return status ;
}
2006-09-27 20:18:14 +00:00
static void event_handler ( switch_event_t * event )
{
char * subclass , * sql ;
2006-09-29 18:12:31 +00:00
if ( ( subclass = switch_event_get_header ( event , " orig-event-subclass " ) ) & & ! strcasecmp ( subclass , MY_EVENT_REGISTER ) ) {
2006-09-27 20:18:14 +00:00
char * from_user = switch_event_get_header ( event , " orig-from-user " ) ;
char * from_host = switch_event_get_header ( event , " orig-from-host " ) ;
2006-10-15 05:10:34 +00:00
char * contact_str = switch_event_get_header ( event , " orig-contact " ) ;
2006-09-27 20:18:14 +00:00
char * exp_str = switch_event_get_header ( event , " orig-expires " ) ;
2006-10-20 06:17:00 +00:00
char * rpid = switch_event_get_header ( event , " orig-rpid " ) ;
2007-03-29 22:31:56 +00:00
long expires = ( long ) time ( NULL ) + atol ( exp_str ) ;
2006-09-27 20:18:14 +00:00
char * profile_name = switch_event_get_header ( event , " orig-profile-name " ) ;
sofia_profile_t * profile ;
char buf [ 512 ] ;
2006-10-20 06:17:00 +00:00
if ( ! rpid ) {
rpid = " unknown " ;
}
2007-03-19 21:09:53 +00:00
if ( ! profile_name | | ! ( profile = find_profile ( profile_name ) ) ) {
2006-09-27 20:18:14 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Profile \n " ) ;
return ;
}
if ( ! find_reg_url ( profile , from_user , from_host , buf , sizeof ( buf ) ) ) {
2007-03-29 22:31:56 +00:00
sql = switch_mprintf ( " insert into sip_registrations values ('%q','%q','%q','Regestered', '%q', %ld) " ,
from_user , from_host , contact_str , rpid , expires ) ;
2006-09-27 20:18:14 +00:00
} else {
2007-03-29 22:31:56 +00:00
sql =
switch_mprintf
( " update sip_registrations set contact='%q', rpid='%q', expires=%ld where user='%q' and host='%q' " ,
contact_str , rpid , expires , from_user , from_host ) ;
2006-09-27 20:18:14 +00:00
}
2007-03-29 22:31:56 +00:00
2006-09-27 20:18:14 +00:00
if ( sql ) {
2006-09-30 00:00:07 +00:00
execute_sql ( profile - > dbname , sql , profile - > ireg_mutex ) ;
2006-10-19 16:33:54 +00:00
switch_safe_free ( sql ) ;
2006-09-27 20:18:14 +00:00
sql = NULL ;
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Propagating registration for %s@%s->%s \n " , from_user , from_host , contact_str ) ;
2006-09-27 20:18:14 +00:00
}
}
}
2006-10-15 05:10:34 +00:00
2006-10-20 22:11:26 +00:00
static switch_status_t chat_send ( char * proto , char * from , char * to , char * subject , char * body , char * hint )
2006-10-18 22:57:35 +00:00
{
char buf [ 256 ] ;
char * user , * host ;
sofia_profile_t * profile ;
2006-10-20 22:11:26 +00:00
char * ffrom = NULL ;
nua_handle_t * msg_nh ;
2006-11-14 18:12:17 +00:00
char * contact ;
2006-10-20 22:11:26 +00:00
2006-10-18 22:57:35 +00:00
if ( to & & ( user = strdup ( to ) ) ) {
if ( ( host = strchr ( user , ' @ ' ) ) ) {
* host + + = ' \0 ' ;
}
2007-03-29 22:31:56 +00:00
2007-03-19 21:09:53 +00:00
if ( ! host | | ! ( profile = find_profile ( host ) ) ) {
2007-03-29 22:31:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR ,
" Chat proto [%s] \n from [%s] \n to [%s] \n %s \n Invalid Profile %s \n " , proto , from , to ,
body ? body : " [no body] " , host ? host : " NULL " ) ;
2006-10-19 07:13:34 +00:00
return SWITCH_STATUS_FALSE ;
2006-10-18 22:57:35 +00:00
}
2007-03-29 22:31:56 +00:00
if ( ! find_reg_url ( profile , user , host , buf , sizeof ( buf ) ) ) {
2006-10-20 22:11:26 +00:00
return SWITCH_STATUS_FALSE ;
}
2006-10-18 22:57:35 +00:00
2006-10-20 22:11:26 +00:00
if ( ! strcmp ( proto , SOFIA_CHAT_PROTO ) ) {
from = hint ;
} else {
char * fp , * p , * fu = NULL ;
2006-10-19 07:13:34 +00:00
2006-10-20 22:11:26 +00:00
if ( ! ( fp = strdup ( from ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Memory Error! \n " ) ;
return SWITCH_STATUS_FALSE ;
}
2006-10-18 22:57:35 +00:00
2006-10-20 22:11:26 +00:00
if ( ( p = strchr ( fp , ' @ ' ) ) ) {
* p = ' \0 ' ;
fu = strdup ( fp ) ;
* p = ' + ' ;
}
2007-03-29 22:31:56 +00:00
ffrom = switch_mprintf ( " \" %s \" <sip:%s+%s@%s> " , fu , proto , fp , profile - > name ) ;
2006-10-20 22:11:26 +00:00
from = ffrom ;
switch_safe_free ( fu ) ;
switch_safe_free ( fp ) ;
2006-10-18 22:57:35 +00:00
}
2006-10-19 07:13:34 +00:00
2006-11-14 18:12:17 +00:00
contact = get_url_from_contact ( buf , 1 ) ;
2007-03-29 22:31:56 +00:00
msg_nh = nua_handle ( profile - > nua , NULL , SIPTAG_FROM_STR ( from ) , NUTAG_URL ( contact ) , SIPTAG_TO_STR ( buf ) , // if this cries, add contact here too, change the 1 to 0 and omit the safe_free
SIPTAG_CONTACT_STR ( profile - > url ) , TAG_END ( ) ) ;
2006-11-14 18:12:17 +00:00
switch_safe_free ( contact ) ;
2007-03-29 22:31:56 +00:00
nua_message ( msg_nh , SIPTAG_CONTENT_TYPE_STR ( " text/html " ) , SIPTAG_PAYLOAD_STR ( body ) , TAG_END ( ) ) ;
2006-10-20 22:11:26 +00:00
switch_safe_free ( ffrom ) ;
2006-10-18 22:57:35 +00:00
free ( user ) ;
}
2007-03-29 22:31:56 +00:00
2006-10-19 07:13:34 +00:00
return SWITCH_STATUS_SUCCESS ;
2006-10-18 22:57:35 +00:00
}
2007-03-29 22:31:56 +00:00
static void cancel_presence ( void )
2006-10-19 19:39:18 +00:00
{
char * sql , * errmsg = NULL ;
switch_core_db_t * db ;
sofia_profile_t * profile ;
switch_hash_index_t * hi ;
2007-03-29 22:31:56 +00:00
void * val ;
2006-10-19 19:39:18 +00:00
2006-10-20 06:17:00 +00:00
if ( ( sql = switch_mprintf ( " select 0,'unavailable','unavailable',* from sip_subscriptions where event='presence' " ) ) ) {
2007-03-19 21:09:53 +00:00
switch_mutex_lock ( globals . hash_mutex ) ;
2007-03-30 00:13:31 +00:00
for ( hi = switch_hash_first ( switch_hash_pool_get ( globals . profile_hash ) , globals . profile_hash ) ; hi ; hi = switch_hash_next ( hi ) ) {
2006-10-19 19:39:18 +00:00
switch_hash_this ( hi , NULL , NULL , & val ) ;
profile = ( sofia_profile_t * ) val ;
if ( ! ( profile - > pflags & PFLAG_PRESENCE ) ) {
continue ;
}
if ( ! ( db = switch_core_db_open_file ( profile - > dbname ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB %s \n " , profile - > dbname ) ;
continue ;
}
switch_mutex_lock ( profile - > ireg_mutex ) ;
switch_core_db_exec ( db , sql , sub_callback , profile , & errmsg ) ;
switch_mutex_unlock ( profile - > ireg_mutex ) ;
switch_core_db_close ( db ) ;
}
switch_safe_free ( sql ) ;
}
2007-03-19 21:09:53 +00:00
switch_mutex_unlock ( globals . hash_mutex ) ;
2006-10-19 19:39:18 +00:00
}
2007-03-29 22:31:56 +00:00
static void establish_presence ( sofia_profile_t * profile )
2006-10-20 22:11:26 +00:00
{
char * sql , * errmsg = NULL ;
switch_core_db_t * db ;
if ( ! ( db = switch_core_db_open_file ( profile - > dbname ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB %s \n " , profile - > dbname ) ;
return ;
}
2006-10-22 04:37:19 +00:00
if ( ( sql = switch_mprintf ( " select user,host,'Registered','unknown','' from sip_registrations " ) ) ) {
switch_mutex_lock ( profile - > ireg_mutex ) ;
switch_core_db_exec ( db , sql , resub_callback , profile , & errmsg ) ;
switch_mutex_unlock ( profile - > ireg_mutex ) ;
switch_safe_free ( sql ) ;
}
if ( ( sql = switch_mprintf ( " select sub_to_user,sub_to_host,'Online','unknown',proto from sip_subscriptions "
" where proto='ext' or proto='user' or proto='conf' " ) ) ) {
2006-10-20 22:11:26 +00:00
switch_mutex_lock ( profile - > ireg_mutex ) ;
switch_core_db_exec ( db , sql , resub_callback , profile , & errmsg ) ;
switch_mutex_unlock ( profile - > ireg_mutex ) ;
switch_safe_free ( sql ) ;
}
switch_core_db_close ( db ) ;
}
2006-10-20 06:17:00 +00:00
static char * translate_rpid ( char * in , char * ext )
{
char * r = NULL ;
if ( in & & ( strstr ( in , " null " ) | | strstr ( in , " NULL " ) ) ) {
in = NULL ;
}
if ( ! in ) {
in = ext ;
}
if ( ! in ) {
return NULL ;
}
2007-03-29 22:31:56 +00:00
2006-10-20 06:17:00 +00:00
if ( ! strcasecmp ( in , " dnd " ) ) {
r = " busy " ;
}
if ( ext & & ! strcasecmp ( ext , " away " ) ) {
r = " idle " ;
}
2007-03-29 22:31:56 +00:00
2006-10-20 06:17:00 +00:00
return r ;
}
2006-10-18 22:57:35 +00:00
static void pres_event_handler ( switch_event_t * event )
2006-10-12 00:59:09 +00:00
{
sofia_profile_t * profile ;
2006-10-15 05:10:34 +00:00
switch_hash_index_t * hi ;
2007-03-29 22:31:56 +00:00
void * val ;
2006-10-12 00:59:09 +00:00
char * from = switch_event_get_header ( event , " from " ) ;
2006-10-20 22:11:26 +00:00
char * proto = switch_event_get_header ( event , " proto " ) ;
2006-10-20 06:17:00 +00:00
char * rpid = switch_event_get_header ( event , " rpid " ) ;
2007-03-29 22:31:56 +00:00
char * status = switch_event_get_header ( event , " status " ) ;
2006-10-15 05:10:34 +00:00
char * event_type = switch_event_get_header ( event , " event_type " ) ;
2006-10-20 22:11:26 +00:00
//char *event_subtype = switch_event_get_header(event, "event_subtype");
char * sql = NULL ;
2006-10-20 06:17:00 +00:00
char * euser = NULL , * user = NULL , * host = NULL ;
2006-10-15 05:10:34 +00:00
char * errmsg ;
switch_core_db_t * db ;
2006-10-20 22:11:26 +00:00
2006-10-20 06:17:00 +00:00
if ( rpid & & ! strcasecmp ( rpid , " n/a " ) ) {
rpid = NULL ;
}
if ( status & & ! strcasecmp ( status , " n/a " ) ) {
status = NULL ;
}
if ( rpid ) {
rpid = translate_rpid ( rpid , status ) ;
2007-03-29 22:31:56 +00:00
}
2006-10-20 06:17:00 +00:00
if ( ! status ) {
status = " Available " ;
if ( rpid ) {
if ( ! strcasecmp ( rpid , " busy " ) ) {
status = " Busy " ;
} else if ( ! strcasecmp ( rpid , " unavailable " ) ) {
status = " Idle " ;
} else if ( ! strcasecmp ( rpid , " away " ) ) {
status = " Idle " ;
}
}
}
2006-10-18 22:57:35 +00:00
2006-10-20 22:11:26 +00:00
if ( ! rpid ) {
rpid = " unknown " ;
}
2006-10-18 22:57:35 +00:00
if ( event - > event_id = = SWITCH_EVENT_ROSTER ) {
2006-10-20 06:17:00 +00:00
if ( from ) {
2007-03-30 00:13:31 +00:00
sql = switch_mprintf ( " select 1,'%q','%q',* from sip_subscriptions where event='presence' and full_from like '%%%q%%' " , status , rpid , from ) ;
2006-10-20 06:17:00 +00:00
} else {
2006-10-20 22:11:26 +00:00
sql = switch_mprintf ( " select 1,'%q','%q',* from sip_subscriptions where event='presence' " , status , rpid ) ;
2006-10-20 06:17:00 +00:00
}
2006-10-18 22:57:35 +00:00
2007-03-19 21:09:53 +00:00
switch_mutex_lock ( globals . hash_mutex ) ;
2007-03-30 00:13:31 +00:00
for ( hi = switch_hash_first ( switch_hash_pool_get ( globals . profile_hash ) , globals . profile_hash ) ; hi ; hi = switch_hash_next ( hi ) ) {
2006-10-18 22:57:35 +00:00
switch_hash_this ( hi , NULL , NULL , & val ) ;
profile = ( sofia_profile_t * ) val ;
if ( ! ( profile - > pflags & PFLAG_PRESENCE ) ) {
continue ;
}
if ( sql ) {
if ( ! ( db = switch_core_db_open_file ( profile - > dbname ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB %s \n " , profile - > dbname ) ;
continue ;
}
switch_mutex_lock ( profile - > ireg_mutex ) ;
switch_core_db_exec ( db , sql , sub_callback , profile , & errmsg ) ;
switch_mutex_unlock ( profile - > ireg_mutex ) ;
switch_core_db_close ( db ) ;
}
}
2007-03-19 21:09:53 +00:00
switch_mutex_unlock ( globals . hash_mutex ) ;
2006-10-18 22:57:35 +00:00
return ;
}
2006-10-15 05:10:34 +00:00
if ( switch_strlen_zero ( event_type ) ) {
2007-03-29 22:31:56 +00:00
event_type = " presence " ;
2006-10-15 05:10:34 +00:00
}
if ( ( user = strdup ( from ) ) ) {
if ( ( host = strchr ( user , ' @ ' ) ) ) {
2006-10-22 04:37:19 +00:00
char * p ;
2006-10-15 05:10:34 +00:00
* host + + = ' \0 ' ;
2006-10-22 04:37:19 +00:00
if ( ( p = strchr ( host , ' / ' ) ) ) {
* p = ' \0 ' ;
}
2006-10-20 22:11:26 +00:00
} else {
switch_safe_free ( user ) ;
return ;
2006-10-15 05:10:34 +00:00
}
2006-10-20 06:17:00 +00:00
if ( ( euser = strchr ( user , ' + ' ) ) ) {
euser + + ;
} else {
euser = user ;
}
2007-03-29 22:31:56 +00:00
2006-10-15 05:10:34 +00:00
} else {
return ;
}
2007-03-29 22:31:56 +00:00
switch ( event - > event_id ) {
case SWITCH_EVENT_PRESENCE_PROBE :
if ( proto ) {
switch_core_db_t * db = NULL ;
char * to = switch_event_get_header ( event , " to " ) ;
char * user , * euser , * host , * p ;
if ( ! to | | ! ( user = strdup ( to ) ) ) {
return ;
}
if ( ( host = strchr ( user , ' @ ' ) ) ) {
* host + + = ' \0 ' ;
}
euser = user ;
if ( ( p = strchr ( euser , ' + ' ) ) ) {
euser = ( p + 1 ) ;
}
if ( euser & & host & &
( sql =
switch_mprintf ( " select user,host,status,rpid,'' from sip_registrations where user='%q' and host='%q' " ,
euser , host ) ) & & ( profile = find_profile ( host ) ) ) {
if ( ! ( db = switch_core_db_open_file ( profile - > dbname ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB %s \n " , profile - > dbname ) ;
switch_safe_free ( user ) ;
switch_safe_free ( sql ) ;
return ;
}
switch_mutex_lock ( profile - > ireg_mutex ) ;
switch_core_db_exec ( db , sql , resub_callback , profile , & errmsg ) ;
switch_mutex_unlock ( profile - > ireg_mutex ) ;
switch_safe_free ( sql ) ;
}
switch_safe_free ( user ) ;
switch_core_db_close ( db ) ;
}
return ;
2006-10-12 00:59:09 +00:00
case SWITCH_EVENT_PRESENCE_IN :
2007-03-29 22:31:56 +00:00
sql =
switch_mprintf
( " select 1,'%q','%q',* from sip_subscriptions where proto='%q' and event='%q' and sub_to_user='%q' and sub_to_host='%q' " ,
status , rpid , proto , event_type , euser , host ) ;
2006-10-12 00:59:09 +00:00
break ;
case SWITCH_EVENT_PRESENCE_OUT :
2007-03-29 22:31:56 +00:00
sql =
switch_mprintf
( " select 0,'%q','%q',* from sip_subscriptions where proto='%q' and event='%q' and sub_to_user='%q' and sub_to_host='%q' " ,
status , rpid , proto , event_type , euser , host ) ;
2006-10-12 00:59:09 +00:00
break ;
default :
break ;
}
2007-03-19 21:09:53 +00:00
switch_mutex_lock ( globals . hash_mutex ) ;
2007-03-30 00:13:31 +00:00
for ( hi = switch_hash_first ( switch_hash_pool_get ( globals . profile_hash ) , globals . profile_hash ) ; hi ; hi = switch_hash_next ( hi ) ) {
2007-03-29 22:31:56 +00:00
switch_hash_this ( hi , NULL , NULL , & val ) ;
profile = ( sofia_profile_t * ) val ;
if ( ! ( profile - > pflags & PFLAG_PRESENCE ) ) {
2006-10-15 05:10:34 +00:00
continue ;
2007-03-29 22:31:56 +00:00
}
2006-10-12 00:59:09 +00:00
2006-10-15 05:10:34 +00:00
if ( sql ) {
if ( ! ( db = switch_core_db_open_file ( profile - > dbname ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB %s \n " , profile - > dbname ) ;
continue ;
}
switch_mutex_lock ( profile - > ireg_mutex ) ;
switch_core_db_exec ( db , sql , sub_callback , profile , & errmsg ) ;
switch_mutex_unlock ( profile - > ireg_mutex ) ;
2007-03-29 22:31:56 +00:00
2006-10-20 06:17:00 +00:00
switch_core_db_close ( db ) ;
2006-10-12 00:59:09 +00:00
}
2006-10-15 05:10:34 +00:00
}
2007-03-19 21:09:53 +00:00
switch_mutex_unlock ( globals . hash_mutex ) ;
2006-10-12 00:59:09 +00:00
2006-10-20 06:17:00 +00:00
switch_safe_free ( sql ) ;
2006-10-15 05:10:34 +00:00
switch_safe_free ( user ) ;
2006-10-12 00:59:09 +00:00
}
2006-09-27 20:18:14 +00:00
2007-03-30 00:13:31 +00:00
SWITCH_MOD_DECLARE ( switch_status_t ) switch_module_load ( const switch_loadable_module_interface_t * * module_interface , char * filename )
2006-08-25 23:55:59 +00:00
{
2006-10-31 21:38:06 +00:00
silence_frame . data = silence_data ;
silence_frame . datalen = sizeof ( silence_data ) ;
silence_frame . buflen = sizeof ( silence_data ) ;
silence_frame . flags = SFF_CNG ;
2006-08-25 23:55:59 +00:00
if ( switch_core_new_memory_pool ( & module_pool ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " OH OH no pool \n " ) ;
return SWITCH_STATUS_TERM ;
}
memset ( & globals , 0 , sizeof ( globals ) ) ;
2006-09-27 03:44:14 +00:00
switch_mutex_init ( & globals . mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
2007-01-19 19:11:44 +00:00
2007-03-29 22:31:56 +00:00
switch_find_local_ip ( globals . guess_ip , sizeof ( globals . guess_ip ) , AF_INET ) ;
2006-09-27 20:18:14 +00:00
2007-03-30 00:13:31 +00:00
if ( switch_event_bind ( ( char * ) modname , SWITCH_EVENT_CUSTOM , MULTICAST_EVENT , event_handler , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
2006-09-27 20:18:14 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
return SWITCH_STATUS_TERM ;
}
2006-08-25 23:55:59 +00:00
su_init ( ) ;
2006-10-09 17:11:39 +00:00
su_log_redirect ( NULL , logger , NULL ) ;
2006-10-15 05:20:49 +00:00
su_log_redirect ( tport_log , logger , NULL ) ;
2006-08-25 23:55:59 +00:00
switch_core_hash_init ( & globals . profile_hash , module_pool ) ;
2007-03-19 21:09:53 +00:00
switch_core_hash_init ( & globals . gateway_hash , module_pool ) ;
2006-08-25 23:55:59 +00:00
switch_mutex_init ( & globals . hash_mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
config_sofia ( 0 ) ;
2006-10-18 22:57:35 +00:00
2007-03-30 00:13:31 +00:00
if ( switch_event_bind ( ( char * ) modname , SWITCH_EVENT_PRESENCE_IN , SWITCH_EVENT_SUBCLASS_ANY , pres_event_handler , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
2006-10-12 00:59:09 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
return SWITCH_STATUS_GENERR ;
}
2006-08-25 23:55:59 +00:00
2007-03-30 00:13:31 +00:00
if ( switch_event_bind ( ( char * ) modname , SWITCH_EVENT_PRESENCE_OUT , SWITCH_EVENT_SUBCLASS_ANY , pres_event_handler , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
2006-10-12 00:59:09 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
2006-12-19 17:48:50 +00:00
return SWITCH_STATUS_GENERR ;
}
2007-03-30 00:13:31 +00:00
if ( switch_event_bind ( ( char * ) modname , SWITCH_EVENT_PRESENCE_PROBE , SWITCH_EVENT_SUBCLASS_ANY , pres_event_handler , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
2006-12-19 17:48:50 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
2006-10-12 00:59:09 +00:00
return SWITCH_STATUS_GENERR ;
}
2007-03-30 00:13:31 +00:00
if ( switch_event_bind ( ( char * ) modname , SWITCH_EVENT_ROSTER , SWITCH_EVENT_SUBCLASS_ANY , pres_event_handler , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
2006-10-12 00:59:09 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
return SWITCH_STATUS_GENERR ;
}
2006-10-09 17:11:39 +00:00
2006-08-25 23:55:59 +00:00
/* connect my internal structure to the blank pointer passed to me */
* module_interface = & sofia_module_interface ;
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_MOD_DECLARE ( switch_status_t ) switch_module_shutdown ( void )
{
2006-09-27 03:44:14 +00:00
2006-10-19 19:39:18 +00:00
cancel_presence ( ) ;
2006-09-27 03:44:14 +00:00
switch_mutex_lock ( globals . mutex ) ;
if ( globals . running = = 1 ) {
globals . running = - 1 ;
}
switch_mutex_unlock ( globals . mutex ) ;
2007-03-29 22:31:56 +00:00
while ( globals . running ) {
2006-09-27 03:44:14 +00:00
switch_yield ( 1000 ) ;
}
2006-08-25 23:55:59 +00:00
su_deinit ( ) ;
return SWITCH_STATUS_SUCCESS ;
}
2006-11-27 22:30:48 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2007-02-09 02:36:03 +00:00
* indent - tabs - mode : t
2006-11-27 22:30:48 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 expandtab :
*/