2007-04-02 19:54:25 +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 >
* Ken Rice , Asteria Solutions Group , Inc < ken @ asteriasgi . com >
* Paul D . Tinsley < pdt at jackhammer . org >
* Bret McDanel < trixter AT 0xdecafbad . com >
*
*
* sofia_presence . c - - SOFIA SIP Endpoint ( presence code )
*
*/
2007-03-31 19:01:33 +00:00
# include "mod_sofia.h"
2007-04-02 19:54:25 +00:00
static int sofia_presence_mwi_callback ( void * pArg , int argc , char * * argv , char * * columnNames ) ;
2007-12-13 23:30:16 +00:00
static int sofia_presence_mwi_callback2 ( void * pArg , int argc , char * * argv , char * * columnNames ) ;
2007-04-02 19:54:25 +00:00
static int sofia_presence_sub_reg_callback ( void * pArg , int argc , char * * argv , char * * columnNames ) ;
static int sofia_presence_resub_callback ( void * pArg , int argc , char * * argv , char * * columnNames ) ;
static int sofia_presence_sub_callback ( void * pArg , int argc , char * * argv , char * * columnNames ) ;
2007-03-31 19:01:33 +00:00
2008-03-14 03:46:54 +00:00
2007-12-15 00:39:53 +00:00
struct presence_helper {
sofia_profile_t * profile ;
switch_event_t * event ;
2007-12-18 01:12:50 +00:00
switch_stream_handle_t stream ;
2008-04-11 19:41:24 +00:00
char last_uuid [ 512 ] ;
2007-12-15 00:39:53 +00:00
} ;
2007-03-31 19:01:33 +00:00
switch_status_t sofia_presence_chat_send ( char * proto , char * from , char * to , char * subject , char * body , char * hint )
{
char buf [ 256 ] ;
char * user , * host ;
2007-04-29 01:16:49 +00:00
sofia_profile_t * profile = NULL ;
2007-03-31 19:01:33 +00:00
char * ffrom = NULL ;
nua_handle_t * msg_nh ;
char * contact ;
2007-11-20 03:26:40 +00:00
if ( ! to ) {
return SWITCH_STATUS_SUCCESS ;
}
2007-03-31 19:01:33 +00:00
2007-11-20 03:26:40 +00:00
user = strdup ( to ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( user ) ;
2007-03-31 19:01:33 +00:00
2007-11-20 03:26:40 +00:00
if ( ( host = strchr ( user , ' @ ' ) ) ) {
* host + + = ' \0 ' ;
}
2007-03-31 19:01:33 +00:00
2007-11-20 03:26:40 +00:00
if ( ! host | | ! ( profile = sofia_glue_find_profile ( host ) ) ) {
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 " ) ;
return SWITCH_STATUS_FALSE ;
}
2007-03-31 19:01:33 +00:00
2007-11-20 03:26:40 +00:00
if ( ! sofia_reg_find_reg_url ( profile , user , host , buf , sizeof ( buf ) ) ) {
return SWITCH_STATUS_FALSE ;
}
2007-03-31 19:01:33 +00:00
2007-11-20 03:26:40 +00:00
if ( ! strcmp ( proto , SOFIA_CHAT_PROTO ) ) {
from = hint ;
} else {
char * fp , * p , * fu = NULL ;
fp = strdup ( from ) ;
if ( ! fp ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Memory Error! \n " ) ;
return SWITCH_STATUS_FALSE ;
}
2007-03-31 19:01:33 +00:00
2007-11-20 03:26:40 +00:00
if ( ( p = strchr ( fp , ' @ ' ) ) ) {
* p = ' \0 ' ;
fu = strdup ( fp ) ;
* p = ' + ' ;
2007-03-31 19:01:33 +00:00
}
2007-11-20 03:26:40 +00:00
ffrom = switch_mprintf ( " \" %s \" <sip:%s+%s@%s> " , fu , proto , fp , profile - > name ) ;
from = ffrom ;
switch_safe_free ( fu ) ;
switch_safe_free ( fp ) ;
}
2007-03-31 19:01:33 +00:00
2007-11-20 03:26:40 +00:00
contact = sofia_glue_get_url_from_contact ( buf , 1 ) ;
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 ( ) ) ;
2007-03-31 19:01:33 +00:00
2007-11-20 03:26:40 +00:00
switch_safe_free ( contact ) ;
2007-03-31 19:01:33 +00:00
2007-11-20 03:26:40 +00:00
nua_message ( msg_nh , SIPTAG_CONTENT_TYPE_STR ( " text/html " ) , SIPTAG_PAYLOAD_STR ( body ) , TAG_END ( ) ) ;
2007-03-31 19:01:33 +00:00
2007-11-20 03:26:40 +00:00
switch_safe_free ( ffrom ) ;
free ( user ) ;
2007-04-29 01:16:49 +00:00
2007-11-20 03:26:40 +00:00
if ( profile ) {
switch_thread_rwlock_unlock ( profile - > rwlock ) ;
2007-03-31 19:01:33 +00:00
}
return SWITCH_STATUS_SUCCESS ;
}
void sofia_presence_cancel ( void )
{
2007-04-04 03:08:17 +00:00
char * sql ;
2007-03-31 19:01:33 +00:00
sofia_profile_t * profile ;
switch_hash_index_t * hi ;
void * val ;
2007-12-18 01:12:50 +00:00
struct presence_helper helper = { 0 } ;
2008-02-04 19:01:22 +00:00
if ( ! mod_sofia_globals . profile_hash ) return ;
2007-10-24 23:20:47 +00:00
if ( ( sql = switch_mprintf ( " select *,-1,'unavailable','unavailable' from sip_subscriptions where event='presence' " ) ) ) {
2007-04-01 01:16:16 +00:00
switch_mutex_lock ( mod_sofia_globals . hash_mutex ) ;
2007-09-24 19:34:25 +00:00
for ( hi = switch_hash_first ( NULL , mod_sofia_globals . profile_hash ) ; hi ; hi = switch_hash_next ( hi ) ) {
2007-03-31 19:01:33 +00:00
switch_hash_this ( hi , NULL , NULL , & val ) ;
profile = ( sofia_profile_t * ) val ;
if ( ! ( profile - > pflags & PFLAG_PRESENCE ) ) {
continue ;
}
2007-12-15 00:39:53 +00:00
helper . profile = profile ;
helper . event = NULL ;
if ( sofia_glue_execute_sql_callback ( profile , SWITCH_FALSE , profile - > ireg_mutex , sql , sofia_presence_sub_callback , & helper ) ! = SWITCH_TRUE ) {
2007-03-31 19:01:33 +00:00
continue ;
}
}
switch_safe_free ( sql ) ;
2007-04-04 03:08:17 +00:00
switch_mutex_unlock ( mod_sofia_globals . hash_mutex ) ;
2007-03-31 19:01:33 +00:00
}
}
2007-04-13 22:15:58 +00:00
void sofia_presence_establish_presence ( sofia_profile_t * profile )
2007-03-31 19:01:33 +00:00
{
2007-04-04 03:08:17 +00:00
if ( sofia_glue_execute_sql_callback ( profile , SWITCH_FALSE , profile - > ireg_mutex ,
2007-11-15 16:55:46 +00:00
" select sip_user,sip_host,'Registered','unknown','' from sip_registrations " ,
2007-04-04 03:08:17 +00:00
sofia_presence_resub_callback , profile ) ! = SWITCH_TRUE ) {
2007-03-31 19:01:33 +00:00
return ;
}
2007-04-04 03:08:17 +00:00
if ( sofia_glue_execute_sql_callback ( profile , SWITCH_FALSE , profile - > ireg_mutex ,
" select sub_to_user,sub_to_host,'Online','unknown',proto from sip_subscriptions "
" where proto='ext' or proto='user' or proto='conf' " ,
sofia_presence_resub_callback , profile ) ! = SWITCH_TRUE ) {
return ;
2007-03-31 19:01:33 +00:00
}
}
char * sofia_presence_translate_rpid ( char * in , char * ext )
{
2007-10-24 23:20:47 +00:00
char * r = in ;
2007-03-31 19:01:33 +00:00
2007-11-15 16:22:18 +00:00
if ( in & & ( switch_stristr ( " null " , in ) ) ) {
2007-03-31 19:01:33 +00:00
in = NULL ;
}
2007-10-24 23:20:47 +00:00
2007-03-31 19:01:33 +00:00
if ( ! in ) {
in = ext ;
}
if ( ! in ) {
return NULL ;
}
2007-10-24 23:20:47 +00:00
if ( ! strcasecmp ( in , " dnd " ) | | ! strcasecmp ( in , " idle " ) ) {
2007-03-31 19:01:33 +00:00
r = " busy " ;
}
return r ;
}
2008-03-14 03:46:54 +00:00
static void actual_sofia_presence_mwi_event_handler ( switch_event_t * event )
2007-04-02 19:54:25 +00:00
{
2008-01-11 01:03:51 +00:00
char * account , * dup_account , * yn , * host , * user ;
2007-04-02 19:54:25 +00:00
char * sql ;
2007-04-29 01:16:49 +00:00
sofia_profile_t * profile = NULL ;
2007-04-02 19:54:25 +00:00
switch_stream_handle_t stream = { 0 } ;
switch_event_header_t * hp ;
2007-12-13 23:30:16 +00:00
int count = 0 ;
2007-12-12 23:21:45 +00:00
switch_assert ( event ! = NULL ) ;
2007-04-02 19:54:25 +00:00
2008-01-11 01:03:51 +00:00
if ( ! ( account = switch_event_get_header ( event , " mwi-message-account " ) ) ) {
2007-04-02 19:54:25 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing required Header 'MWI-Message-Account' \n " ) ;
return ;
}
if ( ! ( yn = switch_event_get_header ( event , " mwi-messages-waiting " ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing required Header 'MWI-Messages-Waiting' \n " ) ;
return ;
}
2008-01-11 01:03:51 +00:00
dup_account = strdup ( account ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( dup_account ! = NULL ) ;
2007-04-02 19:54:25 +00:00
sofia_glue_get_user_host ( dup_account , & user , & host ) ;
if ( ! host | | ! ( profile = sofia_glue_find_profile ( host ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot find profile for host %s \n " , switch_str_nil ( host ) ) ;
return ;
}
2007-04-04 03:08:17 +00:00
2007-04-02 19:54:25 +00:00
SWITCH_STANDARD_STREAM ( stream ) ;
for ( hp = event - > headers ; hp ; hp = hp - > next ) {
if ( ! strncasecmp ( hp - > name , " mwi- " , 4 ) ) {
2007-10-12 22:08:30 +00:00
char * tmp = NULL ;
char * value = hp - > value ;
if ( ! strcasecmp ( hp - > name , " mwi-message-account " ) & & strncasecmp ( hp - > value , " sip: " , 4 ) ) {
tmp = switch_mprintf ( " sip:%s " , hp - > value ) ;
value = tmp ;
}
stream . write_function ( & stream , " %s: %s \r \n " , hp - > name + 4 , value ) ;
switch_safe_free ( tmp ) ;
2007-04-02 19:54:25 +00:00
}
}
stream . write_function ( & stream , " \r \n " ) ;
sql = switch_mprintf ( " select *,'%q' from sip_subscriptions where event='message-summary' and sub_to_user='%q' and sub_to_host='%q' " ,
stream . data , user , host ) ;
2007-12-13 23:30:16 +00:00
2007-04-02 19:54:25 +00:00
2007-12-12 23:21:45 +00:00
switch_assert ( sql ! = NULL ) ;
2007-04-04 03:08:17 +00:00
sofia_glue_execute_sql_callback ( profile ,
SWITCH_FALSE ,
profile - > ireg_mutex ,
sql ,
sofia_presence_mwi_callback ,
2007-12-13 23:30:16 +00:00
& count ) ;
2007-04-04 03:08:17 +00:00
2007-04-02 19:54:25 +00:00
switch_safe_free ( sql ) ;
2007-12-13 23:30:16 +00:00
if ( ! count ) {
2007-12-14 17:39:45 +00:00
sql = switch_mprintf ( " select sip_user,sip_host,contact,'%q' from sip_registrations where sip_user='%q' and sip_host='%q' " ,
2007-12-13 23:30:16 +00:00
stream . data , user , host ) ;
switch_assert ( sql ! = NULL ) ;
sofia_glue_execute_sql_callback ( profile ,
SWITCH_FALSE ,
profile - > ireg_mutex ,
sql ,
sofia_presence_mwi_callback2 ,
profile ) ;
switch_safe_free ( sql ) ;
}
switch_safe_free ( stream . data ) ;
2007-04-02 19:54:25 +00:00
switch_safe_free ( dup_account ) ;
2007-04-29 01:16:49 +00:00
if ( profile ) {
2007-05-03 01:55:25 +00:00
sofia_glue_release_profile ( profile ) ;
2007-04-29 01:16:49 +00:00
}
2007-04-02 19:54:25 +00:00
}
2008-03-14 03:46:54 +00:00
static void actual_sofia_presence_event_handler ( switch_event_t * event )
2007-03-31 19:01:33 +00:00
{
2007-04-29 01:16:49 +00:00
sofia_profile_t * profile = NULL ;
2007-03-31 19:01:33 +00:00
switch_hash_index_t * hi ;
void * val ;
char * from = switch_event_get_header ( event , " from " ) ;
char * proto = switch_event_get_header ( event , " proto " ) ;
char * rpid = switch_event_get_header ( event , " rpid " ) ;
char * status = switch_event_get_header ( event , " status " ) ;
char * event_type = switch_event_get_header ( event , " event_type " ) ;
2007-12-15 00:39:53 +00:00
char * alt_event_type = switch_event_get_header ( event , " alt_event_type " ) ;
2007-03-31 19:01:33 +00:00
char * sql = NULL ;
char * euser = NULL , * user = NULL , * host = NULL ;
2008-03-14 03:46:54 +00:00
if ( ! mod_sofia_globals . running ) {
return ;
}
2007-03-31 19:01:33 +00:00
if ( rpid & & ! strcasecmp ( rpid , " n/a " ) ) {
rpid = NULL ;
}
if ( status & & ! strcasecmp ( status , " n/a " ) ) {
status = NULL ;
}
if ( rpid ) {
rpid = sofia_presence_translate_rpid ( rpid , status ) ;
}
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 " ;
}
}
}
if ( ! rpid ) {
rpid = " unknown " ;
}
if ( event - > event_id = = SWITCH_EVENT_ROSTER ) {
2007-12-18 01:12:50 +00:00
struct presence_helper helper = { 0 } ;
2008-02-04 19:01:22 +00:00
if ( ! mod_sofia_globals . profile_hash ) return ;
2007-12-15 00:39:53 +00:00
2007-03-31 19:01:33 +00:00
if ( from ) {
2007-10-24 23:20:47 +00:00
sql = switch_mprintf ( " select *,1,'%q','%q' from sip_subscriptions where event='presence' and full_from like '%%%q%%' " , status , rpid , from ) ;
2007-03-31 19:01:33 +00:00
} else {
2007-10-24 23:20:47 +00:00
sql = switch_mprintf ( " select *,1,'%q','%q' from sip_subscriptions where event='presence' " , status , rpid ) ;
2007-03-31 19:01:33 +00:00
}
2007-10-24 23:20:47 +00:00
2007-12-12 23:21:45 +00:00
switch_assert ( sql ! = NULL ) ;
2007-04-01 01:16:16 +00:00
switch_mutex_lock ( mod_sofia_globals . hash_mutex ) ;
2007-09-24 19:34:25 +00:00
for ( hi = switch_hash_first ( NULL , mod_sofia_globals . profile_hash ) ; hi ; hi = switch_hash_next ( hi ) ) {
2007-03-31 19:01:33 +00:00
switch_hash_this ( hi , NULL , NULL , & val ) ;
profile = ( sofia_profile_t * ) val ;
if ( ! ( profile - > pflags & PFLAG_PRESENCE ) ) {
continue ;
}
2007-12-15 00:39:53 +00:00
helper . profile = profile ;
helper . event = NULL ;
2007-04-04 03:08:17 +00:00
sofia_glue_execute_sql_callback ( profile ,
SWITCH_FALSE ,
profile - > ireg_mutex ,
sql ,
sofia_presence_sub_callback ,
2007-12-15 00:39:53 +00:00
& helper ) ;
2007-03-31 19:01:33 +00:00
}
2007-04-01 01:16:16 +00:00
switch_mutex_unlock ( mod_sofia_globals . hash_mutex ) ;
2007-04-04 03:08:17 +00:00
free ( sql ) ;
2007-03-31 19:01:33 +00:00
return ;
}
if ( switch_strlen_zero ( event_type ) ) {
event_type = " presence " ;
}
2007-12-15 00:39:53 +00:00
if ( switch_strlen_zero ( alt_event_type ) ) {
alt_event_type = " presence " ;
}
2007-03-31 19:01:33 +00:00
if ( ( user = strdup ( from ) ) ) {
if ( ( host = strchr ( user , ' @ ' ) ) ) {
char * p ;
* host + + = ' \0 ' ;
if ( ( p = strchr ( host , ' / ' ) ) ) {
* p = ' \0 ' ;
}
} else {
switch_safe_free ( user ) ;
return ;
}
if ( ( euser = strchr ( user , ' + ' ) ) ) {
euser + + ;
} else {
euser = user ;
}
} else {
return ;
}
switch ( event - > event_id ) {
case SWITCH_EVENT_PRESENCE_PROBE :
if ( proto ) {
char * to = switch_event_get_header ( event , " to " ) ;
2007-12-13 04:01:29 +00:00
char * probe_user , * probe_euser , * probe_host , * p ;
2007-03-31 19:01:33 +00:00
2007-12-13 04:01:29 +00:00
if ( ! to | | ! ( probe_user = strdup ( to ) ) ) {
2007-03-31 19:01:33 +00:00
return ;
}
2007-12-13 04:01:29 +00:00
if ( ( probe_host = strchr ( probe_user , ' @ ' ) ) ) {
* probe_host + + = ' \0 ' ;
2007-03-31 19:01:33 +00:00
}
2007-12-13 04:01:29 +00:00
probe_euser = probe_user ;
if ( ( p = strchr ( probe_euser , ' + ' ) ) ) {
probe_euser = ( p + 1 ) ;
2007-03-31 19:01:33 +00:00
}
2007-12-18 01:12:50 +00:00
if ( probe_euser & & probe_host & & ( profile = sofia_glue_find_profile ( probe_host ) ) ) {
sql = switch_mprintf ( " select sip_registrations.sip_user, sip_registrations.sip_host, sip_registrations.status, "
" sip_registrations.rpid,'', sip_dialogs.uuid, sip_dialogs.state, sip_dialogs.direction "
" from sip_registrations left join sip_dialogs on "
2007-12-18 03:12:51 +00:00
" (sip_dialogs.sip_from_user = sip_registrations.sip_user) "
" and sip_dialogs.sip_from_host = sip_registrations.sip_host "
2007-12-18 01:12:50 +00:00
" where sip_registrations.sip_user='%q' and sip_registrations.sip_host='%q' " ,
probe_euser , probe_host ) ;
switch_assert ( sql ) ;
2007-04-04 03:08:17 +00:00
sofia_glue_execute_sql_callback ( profile ,
SWITCH_FALSE ,
profile - > ireg_mutex ,
sql ,
sofia_presence_resub_callback ,
profile ) ;
2007-03-31 19:01:33 +00:00
2007-05-03 01:55:25 +00:00
sofia_glue_release_profile ( profile ) ;
2007-03-31 19:01:33 +00:00
switch_safe_free ( sql ) ;
}
2007-12-18 01:12:50 +00:00
2007-03-31 19:01:33 +00:00
switch_safe_free ( user ) ;
}
return ;
case SWITCH_EVENT_PRESENCE_IN :
sql =
switch_mprintf
2007-12-15 18:26:10 +00:00
( " select *,1,'%q','%q' from sip_subscriptions where (event='%q' or event='%q') and sub_to_user='%q' and sub_to_host='%q' " ,
status , rpid , event_type , alt_event_type , euser , host ) ;
2007-03-31 19:01:33 +00:00
break ;
case SWITCH_EVENT_PRESENCE_OUT :
sql =
switch_mprintf
2007-12-15 18:26:10 +00:00
( " select *,0,'%q','%q' from sip_subscriptions where (event='%q' or event='%q') and sub_to_user='%q' and sub_to_host='%q' " ,
status , rpid , event_type , alt_event_type , euser , host ) ;
2007-03-31 19:01:33 +00:00
break ;
default :
break ;
}
2008-02-04 19:01:22 +00:00
if ( ! mod_sofia_globals . profile_hash ) goto done ;
2007-04-01 01:16:16 +00:00
switch_mutex_lock ( mod_sofia_globals . hash_mutex ) ;
2007-09-24 19:34:25 +00:00
for ( hi = switch_hash_first ( NULL , mod_sofia_globals . profile_hash ) ; hi ; hi = switch_hash_next ( hi ) ) {
2007-03-31 19:01:33 +00:00
switch_hash_this ( hi , NULL , NULL , & val ) ;
profile = ( sofia_profile_t * ) val ;
if ( ! ( profile - > pflags & PFLAG_PRESENCE ) ) {
continue ;
}
if ( sql ) {
2007-12-18 01:12:50 +00:00
struct presence_helper helper = { 0 } ;
2007-12-15 00:39:53 +00:00
helper . profile = profile ;
helper . event = event ;
2007-12-18 01:12:50 +00:00
SWITCH_STANDARD_STREAM ( helper . stream ) ;
2008-03-14 03:46:54 +00:00
switch_assert ( helper . stream . data ) ;
2007-04-04 03:08:17 +00:00
sofia_glue_execute_sql_callback ( profile ,
SWITCH_FALSE ,
2008-03-14 03:46:54 +00:00
//profile->ireg_mutex,
NULL ,
2007-04-04 03:08:17 +00:00
sql ,
sofia_presence_sub_callback ,
2007-12-15 00:39:53 +00:00
& helper ) ;
2007-12-18 01:12:50 +00:00
2008-04-11 17:07:06 +00:00
if ( ! switch_strlen_zero ( ( char * ) helper . stream . data ) ) {
char * this = ( char * ) helper . stream . data ;
char * next = NULL ;
2008-04-11 19:41:24 +00:00
char * last = NULL ;
2008-04-11 17:07:06 +00:00
do {
if ( ( next = strchr ( this , ' ; ' ) ) ) {
* next + + = ' \0 ' ;
while ( * next = = ' \n ' | | * next = = ' ' | | * next = = ' \r ' ) {
* next + + = ' \0 ' ;
}
}
2008-04-11 19:41:24 +00:00
if ( ! switch_strlen_zero ( this ) & & ( ! last | | strcmp ( last , this ) ) ) {
2008-04-11 17:07:06 +00:00
sofia_glue_execute_sql ( profile , & this , SWITCH_FALSE ) ;
2008-04-11 19:41:24 +00:00
last = this ;
2008-04-11 17:07:06 +00:00
}
this = next ;
} while ( this ) ;
2007-12-18 01:12:50 +00:00
}
2008-04-11 17:07:06 +00:00
switch_safe_free ( helper . stream . data ) ;
2008-03-14 03:46:54 +00:00
helper . stream . data = NULL ;
2007-03-31 19:01:33 +00:00
}
}
2007-04-01 01:16:16 +00:00
switch_mutex_unlock ( mod_sofia_globals . hash_mutex ) ;
2007-03-31 19:01:33 +00:00
2008-02-04 19:01:22 +00:00
done :
2007-03-31 19:01:33 +00:00
switch_safe_free ( sql ) ;
switch_safe_free ( user ) ;
}
2008-03-14 13:05:28 +00:00
static int EVENT_THREAD_RUNNING = 0 ;
static int EVENT_THREAD_STARTED = 0 ;
2008-03-14 03:46:54 +00:00
void * SWITCH_THREAD_FUNC sofia_presence_event_thread_run ( switch_thread_t * thread , void * obj )
{
void * pop ;
2008-03-14 13:05:28 +00:00
int done = 0 ;
2008-03-14 03:46:54 +00:00
switch_mutex_lock ( mod_sofia_globals . mutex ) ;
2008-03-14 13:05:28 +00:00
if ( ! EVENT_THREAD_RUNNING ) {
EVENT_THREAD_RUNNING + + ;
mod_sofia_globals . threads + + ;
} else {
done = 1 ;
}
2008-03-14 03:46:54 +00:00
switch_mutex_unlock ( mod_sofia_globals . mutex ) ;
2008-03-14 13:05:28 +00:00
if ( done ) {
return NULL ;
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Event Thread Started \n " ) ;
2008-03-14 03:46:54 +00:00
while ( mod_sofia_globals . running = = 1 ) {
int count = 0 ;
if ( switch_queue_trypop ( mod_sofia_globals . presence_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_t * event = ( switch_event_t * ) pop ;
if ( ! pop ) {
break ;
}
actual_sofia_presence_event_handler ( event ) ;
switch_event_destroy ( & event ) ;
count + + ;
}
if ( switch_queue_trypop ( mod_sofia_globals . mwi_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_t * event = ( switch_event_t * ) pop ;
if ( ! pop ) {
break ;
}
actual_sofia_presence_mwi_event_handler ( event ) ;
switch_event_destroy ( & event ) ;
count + + ;
}
if ( ! count ) {
switch_yield ( 100000 ) ;
}
}
while ( switch_queue_trypop ( mod_sofia_globals . presence_queue , & pop ) = = SWITCH_STATUS_SUCCESS & & pop ) {
switch_event_t * event = ( switch_event_t * ) pop ;
switch_event_destroy ( & event ) ;
}
while ( switch_queue_trypop ( mod_sofia_globals . mwi_queue , & pop ) = = SWITCH_STATUS_SUCCESS & & pop ) {
switch_event_t * event = ( switch_event_t * ) pop ;
switch_event_destroy ( & event ) ;
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Event Thread Ended \n " ) ;
switch_mutex_lock ( mod_sofia_globals . mutex ) ;
mod_sofia_globals . threads - - ;
2008-03-14 13:05:28 +00:00
EVENT_THREAD_RUNNING = EVENT_THREAD_STARTED = 0 ;
2008-03-14 03:46:54 +00:00
switch_mutex_unlock ( mod_sofia_globals . mutex ) ;
2008-03-14 13:05:28 +00:00
2008-03-14 03:46:54 +00:00
return NULL ;
}
void sofia_presence_event_thread_start ( void )
{
switch_thread_t * thread ;
switch_threadattr_t * thd_attr = NULL ;
2008-03-14 13:05:28 +00:00
int done = 0 ;
switch_mutex_lock ( mod_sofia_globals . mutex ) ;
if ( ! EVENT_THREAD_STARTED ) {
EVENT_THREAD_STARTED + + ;
} else {
done = 1 ;
}
switch_mutex_unlock ( mod_sofia_globals . mutex ) ;
if ( done ) {
return ;
}
2008-03-14 03:46:54 +00:00
switch_threadattr_create ( & thd_attr , mod_sofia_globals . pool ) ;
switch_threadattr_detach_set ( thd_attr , 1 ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
switch_threadattr_priority_increase ( thd_attr ) ;
switch_thread_create ( & thread , thd_attr , sofia_presence_event_thread_run , NULL , mod_sofia_globals . pool ) ;
}
void sofia_presence_event_handler ( switch_event_t * event )
{
switch_event_t * cloned_event ;
switch_event_dup ( & cloned_event , event ) ;
switch_assert ( cloned_event ) ;
switch_queue_push ( mod_sofia_globals . presence_queue , cloned_event ) ;
2008-03-14 13:05:28 +00:00
if ( ! EVENT_THREAD_STARTED ) {
sofia_presence_event_thread_start ( ) ;
}
2008-03-14 03:46:54 +00:00
}
void sofia_presence_mwi_event_handler ( switch_event_t * event )
{
switch_event_t * cloned_event ;
switch_event_dup ( & cloned_event , event ) ;
switch_assert ( cloned_event ) ;
switch_queue_push ( mod_sofia_globals . mwi_queue , cloned_event ) ;
2008-03-14 13:05:28 +00:00
if ( ! EVENT_THREAD_STARTED ) {
sofia_presence_event_thread_start ( ) ;
}
2008-03-14 03:46:54 +00:00
}
2007-04-02 19:54:25 +00:00
static int sofia_presence_sub_reg_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
2007-03-31 19:01:33 +00:00
{
sofia_profile_t * profile = ( sofia_profile_t * ) pArg ;
char * user = argv [ 1 ] ;
char * host = argv [ 2 ] ;
switch_event_t * event ;
char * status = NULL ;
2007-04-02 19:54:25 +00:00
char * event_name = argv [ 5 ] ;
if ( ! strcasecmp ( event_name , " message-summary " ) ) {
2007-04-02 20:20:46 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_MESSAGE_QUERY ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Message-Account " , " sip:%s@%s " , user , host ) ;
2007-04-02 19:54:25 +00:00
switch_event_fire ( & event ) ;
}
return 0 ;
}
2007-03-31 19:01:33 +00:00
if ( switch_strlen_zero ( status ) ) {
status = " Available " ;
}
2007-12-15 00:39:53 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_PROBE ) = = SWITCH_STATUS_SUCCESS ) {
2007-03-31 19:01:33 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
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 , " event_type " , " presence " ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " event_subtype " , " probe " ) ;
2007-12-15 00:39:53 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto-specific-event-name " , " %s " , event_name ) ;
2007-03-31 19:01:33 +00:00
switch_event_fire ( & event ) ;
}
return 0 ;
}
2007-04-02 19:54:25 +00:00
static int sofia_presence_resub_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
2007-03-31 19:01:33 +00:00
{
sofia_profile_t * profile = ( sofia_profile_t * ) pArg ;
char * user = argv [ 0 ] ;
char * host = argv [ 1 ] ;
char * status = argv [ 2 ] ;
char * rpid = argv [ 3 ] ;
char * proto = argv [ 4 ] ;
2007-12-18 01:12:50 +00:00
char * uuid = NULL ;
char * state = NULL ;
char * direction = NULL ;
2007-03-31 19:01:33 +00:00
switch_event_t * event ;
2007-12-18 01:12:50 +00:00
if ( argc > 5 ) {
uuid = switch_str_nil ( argv [ 5 ] ) ;
state = switch_str_nil ( argv [ 6 ] ) ;
direction = switch_str_nil ( argv [ 7 ] ) ;
}
2007-03-31 19:01:33 +00:00
if ( switch_strlen_zero ( proto ) ) {
proto = NULL ;
}
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , " %s " , proto ? proto : SOFIA_CHAT_PROTO ) ;
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 " ) ;
2007-12-18 01:12:50 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " alt_event_type " , " dialog " ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " event_count " , " %d " , 0 ) ;
if ( switch_strlen_zero ( state ) ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " unique-id " , " %s " , SOFIA_CHAT_PROTO ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " channel-state " , " %s " , " CS_HANGUP " ) ;
2007-12-29 17:50:38 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " answer-state " , " %s " , " resubscribe " ) ;
2007-12-18 01:12:50 +00:00
} else {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " channel-state " , " %s " , " CS_RING " ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " unique-id " , " %s " , uuid ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " answer-state " , " %s " , state ) ;
2007-12-18 03:12:51 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " astate " , " %s " , state ) ;
2007-12-18 01:12:50 +00:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " call-direction " , " %s " , direction ) ;
}
2007-12-15 18:26:10 +00:00
2007-03-31 19:01:33 +00:00
switch_event_fire ( & event ) ;
}
return 0 ;
}
2007-10-24 23:20:47 +00:00
static char * translate_rpid ( char * in )
{
char * r = in ;
if ( in & & ( strstr ( in , " null " ) | | strstr ( in , " NULL " ) ) ) {
in = NULL ;
}
if ( ! in | | ! strcasecmp ( in , " unknown " ) ) {
r = " online " ;
goto end ;
}
if ( ! strcasecmp ( in , " busy " ) ) {
r = in ;
goto end ;
}
if ( ! strcasecmp ( in , " unavailable " ) ) {
r = " away " ;
goto end ;
}
if ( ! strcasecmp ( in , " idle " ) ) {
r = " busy " ;
}
end :
return r ;
}
2007-04-02 19:54:25 +00:00
static int sofia_presence_sub_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
2007-03-31 19:01:33 +00:00
{
2007-12-15 00:39:53 +00:00
struct presence_helper * helper = ( struct presence_helper * ) pArg ;
sofia_profile_t * profile = helper - > profile ;
2007-12-18 01:12:50 +00:00
char * pl = NULL ;
char * clean_id = NULL , * id = NULL , * note = NULL ;
2007-12-14 02:09:22 +00:00
uint32_t in = atoi ( argv [ 13 ] ) ;
char * status = argv [ 14 ] ;
char * rpid = argv [ 15 ] ;
2007-10-24 23:20:47 +00:00
char * proto = argv [ 0 ] ;
char * user = argv [ 1 ] ;
char * host = argv [ 2 ] ;
char * sub_to_user = argv [ 3 ] ;
char * sub_to_host = argv [ 4 ] ;
char * event = argv [ 5 ] ;
char * call_id = argv [ 7 ] ;
2007-12-29 16:07:03 +00:00
char * expires = argv [ 10 ] ;
2008-02-14 17:28:58 +00:00
//char *accept = argv[12];
2007-03-31 19:01:33 +00:00
nua_handle_t * nh ;
2007-12-18 01:12:50 +00:00
char * to = NULL ;
2007-03-31 19:01:33 +00:00
char * open ;
2007-10-24 23:20:47 +00:00
char * prpid ;
int done = 0 ;
2008-02-14 17:51:16 +00:00
const char * ct = " no/idea " ;
2008-01-11 00:43:49 +00:00
time_t exptime = switch_timestamp ( NULL ) + 3600 ;
2007-12-29 16:07:03 +00:00
char exp [ 80 ] = " " ;
2008-02-14 17:28:58 +00:00
int is_dialog = 0 ;
2007-12-29 16:07:03 +00:00
if ( expires ) {
long tmp = atol ( expires ) ;
if ( tmp > 0 ) {
2008-01-11 00:43:49 +00:00
exptime = tmp - switch_timestamp ( NULL ) ;
2007-12-29 16:07:03 +00:00
}
}
2007-10-24 23:20:47 +00:00
if ( ! ( nh = ( nua_handle_t * ) switch_core_hash_find ( profile - > sub_hash , call_id ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot find handle for %s \n " , call_id ) ;
return 0 ;
}
2007-03-31 19:01:33 +00:00
if ( ! rpid ) {
rpid = " unknown " ;
}
2007-10-24 23:20:47 +00:00
prpid = translate_rpid ( rpid ) ;
if ( in < 0 ) {
done = 1 ;
in = 0 ;
}
2007-12-18 01:12:50 +00:00
if ( ! strcasecmp ( proto , SOFIA_CHAT_PROTO ) ) {
clean_id = switch_mprintf ( " sip:%s@%s " , sub_to_user , sub_to_host ) ;
} else {
clean_id = switch_mprintf ( " sip:%s+%s@%s " , proto , sub_to_user , sub_to_host ) ;
}
2007-12-15 18:26:10 +00:00
2007-03-31 19:01:33 +00:00
if ( ! strcasecmp ( sub_to_host , host ) ) {
/* same host */
id = switch_mprintf ( " sip:%s+%s@%s " , proto , sub_to_user , sub_to_host ) ;
} else if ( strcasecmp ( proto , SOFIA_CHAT_PROTO ) ) {
/*encapsulate */
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 ) ;
2008-02-14 17:28:58 +00:00
is_dialog = ! strcmp ( event , " dialog " ) ;
2007-12-15 00:39:53 +00:00
2008-02-14 17:28:58 +00:00
if ( helper - > event ) {
2007-12-15 00:39:53 +00:00
switch_stream_handle_t stream = { 0 } ;
2007-12-18 01:12:50 +00:00
const char * direction = switch_str_nil ( switch_event_get_header ( helper - > event , " call-direction " ) ) ;
2007-12-15 00:39:53 +00:00
const char * uuid = switch_str_nil ( switch_event_get_header ( helper - > event , " unique-id " ) ) ;
const char * state = switch_str_nil ( switch_event_get_header ( helper - > event , " channel-state " ) ) ;
2007-12-15 19:33:36 +00:00
const char * event_status = switch_str_nil ( switch_event_get_header ( helper - > event , " status " ) ) ;
2007-12-18 03:12:51 +00:00
const char * astate = switch_str_nil ( switch_event_get_header ( helper - > event , " astate " ) ) ;
2007-12-29 18:30:48 +00:00
const char * answer_state = switch_str_nil ( switch_event_get_header ( helper - > event , " answer-state " ) ) ;
2007-12-18 01:12:50 +00:00
const char * dft_state ;
2008-02-14 17:28:58 +00:00
const char * from_id = switch_str_nil ( switch_event_get_header ( helper - > event , " Other-Leg-Caller-ID-Number " ) ) ;
const char * to_user = switch_str_nil ( switch_event_get_header ( helper - > event , " variable_sip_to_user " ) ) ;
const char * from_user = switch_str_nil ( switch_event_get_header ( helper - > event , " variable_sip_from_user " ) ) ;
const char * clean_to_user = NULL ;
const char * clean_from_user = NULL ;
2007-12-18 01:12:50 +00:00
2008-02-14 17:28:58 +00:00
if ( is_dialog ) {
SWITCH_STANDARD_STREAM ( stream ) ;
}
2007-12-18 03:12:51 +00:00
2007-12-18 01:12:50 +00:00
if ( ! strcasecmp ( direction , " outbound " ) ) {
direction = " recipient " ;
dft_state = " early " ;
} else {
direction = " initiator " ;
dft_state = " confirmed " ;
}
2007-12-18 03:12:51 +00:00
2007-12-20 02:55:36 +00:00
if ( ! strcasecmp ( state , " cs_execute " ) & & ! strstr ( event_status , " hold " ) ) {
2007-12-18 01:12:50 +00:00
goto end ;
2007-12-20 02:55:36 +00:00
}
2007-12-29 17:50:38 +00:00
if ( ! strcasecmp ( event_status , " Registered " ) ) {
answer_state = " resubscribe " ;
}
2008-02-14 17:28:58 +00:00
if ( is_dialog ) {
stream . write_function ( & stream ,
" <?xml version= \" 1.0 \" ?> \n "
" <dialog-info xmlns= \" urn:ietf:params:xml:ns:dialog-info \" "
" version= \" %s \" state= \" %s \" entity= \" %s \" > \n " ,
switch_str_nil ( switch_event_get_header ( helper - > event , " event_count " ) ) ,
! strcasecmp ( answer_state , " resubscribe " ) ? " partial " : " full " , clean_id ) ;
}
2007-12-29 17:50:38 +00:00
if ( strcasecmp ( answer_state , " resubscribe " ) ) {
2007-12-20 02:55:36 +00:00
2008-01-01 01:03:33 +00:00
if ( ! strcasecmp ( state , " cs_hangup " ) ) {
astate = " terminated " ;
} else if ( switch_strlen_zero ( astate ) ) {
astate = switch_str_nil ( switch_event_get_header ( helper - > event , " answer-state " ) ) ;
if ( switch_strlen_zero ( astate ) ) {
astate = dft_state ;
}
}
if ( ! strcasecmp ( event_status , " hold " ) ) {
2007-12-18 03:12:51 +00:00
astate = " early " ;
2008-01-01 01:03:33 +00:00
}
if ( ! strcasecmp ( astate , " answered " ) ) {
2007-12-18 03:12:51 +00:00
astate = " confirmed " ;
}
2008-01-01 01:03:33 +00:00
if ( ! strcasecmp ( astate , " ringing " ) ) {
if ( ! strcasecmp ( direction , " recipient " ) ) {
astate = " early " ;
} else {
astate = " confirmed " ;
}
}
2008-02-14 17:28:58 +00:00
if ( is_dialog ) {
stream . write_function ( & stream , " <dialog id= \" %s \" direction= \" %s \" > \n " , uuid , direction ) ;
stream . write_function ( & stream , " <state>%s</state> \n " , astate ) ;
}
if ( ! strcasecmp ( astate , " early " ) | | ! strcasecmp ( astate , " confirmed " ) ) {
2007-12-29 17:50:38 +00:00
2008-02-14 17:28:58 +00:00
clean_to_user = switch_mprintf ( " %s " , sub_to_user ? sub_to_user : to_user ) ;
clean_from_user = switch_mprintf ( " %s " , from_id ? from_id : from_user ) ;
if ( is_dialog ) {
2008-02-15 23:18:18 +00:00
if ( ! switch_strlen_zero ( clean_to_user ) & & ! switch_strlen_zero ( clean_from_user ) ) {
2008-02-14 17:28:58 +00:00
stream . write_function ( & stream , " <local> \n <identity display= \" %s \" >sip:%s@%s</identity> \n " , clean_to_user , clean_to_user , host ) ;
stream . write_function ( & stream , " <target uri= \" sip:%s@%s \" > \n " , clean_to_user , host ) ;
stream . write_function ( & stream , " <param pname= \" +sip.rendering \" pvalue= \" %s \" /> \n " , ! strcasecmp ( event_status , " hold " ) ? " no " : " yes " ) ;
stream . write_function ( & stream , " </target> \n </local> \n " ) ;
stream . write_function ( & stream , " <remote> \n <identity display= \" %s \" >sip:%s@%s</identity> \n " , clean_from_user , clean_from_user , host ) ;
stream . write_function ( & stream , " <target uri= \" sip:**%s@%s \" /> \n " , clean_to_user , host ) ;
stream . write_function ( & stream , " </remote> \n " ) ;
} else if ( ! strcasecmp ( proto , " park " ) ) {
stream . write_function ( & stream , " <local> \n <identity display= \" parking \" >sip:parking@%s;fifo=%s</identity> \n " ,
host , ! switch_strlen_zero ( clean_to_user ) ? clean_to_user : " unknown " ) ;
stream . write_function ( & stream , " <target uri= \" sip:parking@%s \" > \n " , host ) ;
stream . write_function ( & stream , " <param pname= \" +sip.rendering \" pvalue= \" no \" /> \n </target> \n </local> \n " ) ;
stream . write_function ( & stream , " <remote> \n <identity display= \" parking \" >sip:%s</identity> \n " , uuid ) ;
stream . write_function ( & stream , " <target uri= \" sip:park+%s \" /> \n " , uuid ) ;
stream . write_function ( & stream , " </remote> \n " ) ;
} else if ( ! strcasecmp ( proto , " conf " ) ) {
stream . write_function ( & stream , " <local> \n <identity display= \" conference \" >sip:conference@%s;conference=%s</identity> \n " ,
host , ! switch_strlen_zero ( clean_to_user ) ? clean_to_user : " unknown " ) ;
stream . write_function ( & stream , " <target uri= \" sip:conference@%s \" > \n " , host ) ;
stream . write_function ( & stream , " <param pname= \" +sip.rendering \" pvalue= \" yes \" /> \n </target> \n </local> \n " ) ;
stream . write_function ( & stream , " <remote> \n <identity display= \" conference \" >sip:%s@%s</identity> \n " , uuid , host ) ;
stream . write_function ( & stream , " <target uri= \" sip:conf+%s@%s \" /> \n " , uuid , host ) ;
stream . write_function ( & stream , " </remote> \n " ) ;
}
2007-12-29 17:50:38 +00:00
}
}
2008-02-14 17:28:58 +00:00
if ( is_dialog ) {
stream . write_function ( & stream , " </dialog> \n " ) ;
}
}
if ( is_dialog ) {
stream . write_function ( & stream , " </dialog-info> \n " ) ;
pl = stream . data ;
ct = " application/dialog-info+xml " ;
}
2008-04-11 19:41:24 +00:00
if ( ! switch_strlen_zero ( astate ) & & ! switch_strlen_zero ( uuid ) & & helper & & helper - > stream . data & & strcmp ( helper - > last_uuid , uuid ) ) {
helper - > stream . write_function ( & helper - > stream , " update sip_dialogs set state='%s' where uuid='%s'; " , astate , uuid ) ;
switch_copy_string ( helper - > last_uuid , uuid , sizeof ( helper - > last_uuid ) ) ;
2007-12-29 17:50:38 +00:00
}
2007-12-29 17:52:22 +00:00
2007-12-15 18:26:10 +00:00
2008-02-14 17:28:58 +00:00
if ( ! is_dialog ) {
if ( in ) {
char status_line [ 256 ] = " " ;
if ( ! strcmp ( astate , " early " ) ) {
switch_snprintf ( status_line , sizeof ( status_line ) , " R %s " , switch_str_nil ( from_id ) ) ;
2008-02-14 19:45:15 +00:00
rpid = " on-the-phone " ;
2008-02-14 17:28:58 +00:00
} else if ( ! strcmp ( astate , " confirmed " ) ) {
char * dest = switch_event_get_header ( helper - > event , " Caller-Destination-Number " ) ;
if ( switch_strlen_zero ( from_id ) & & ! switch_strlen_zero ( dest ) ) {
from_id = dest ;
}
2008-02-14 19:45:15 +00:00
if ( switch_strlen_zero ( from_id ) ) {
switch_snprintf ( status_line , sizeof ( status_line ) , " Available " ) ;
} else {
switch_snprintf ( status_line , sizeof ( status_line ) , " T %s " , switch_str_nil ( from_id ) ) ;
rpid = " on-the-phone " ;
}
2008-02-14 17:28:58 +00:00
} else if ( ! strcmp ( astate , " terminated " ) ) {
switch_snprintf ( status_line , sizeof ( status_line ) , " Available " ) ;
}
2007-12-29 18:30:48 +00:00
2008-02-14 17:28:58 +00:00
note = switch_mprintf ( " <dm:note>%s</dm:note> " , status_line ) ;
open = " open " ;
} else {
note = NULL ;
open = " closed " ;
}
prpid = translate_rpid ( rpid ) ;
pl = switch_mprintf ( " <?xml version='1.0' encoding='UTF-8'?> \r \n "
" <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 "
" <presentity uri= \" %s;method=SUBSCRIBE \" /> \r \n "
" <atom id= \" 1002 \" > \r \n "
" <address uri= \" %s \" priority= \" 0.800000 \" > \r \n "
" <status status= \" %s \" > \r \n "
" <note>%s</note> \r \n "
" </status> \r \n "
" <msnsubstatus substatus= \" %s \" /> \r \n "
" </address> \r \n "
" </atom> \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 "
" <rpid:activities> \r \n " " <rpid:%s/> \r \n "
" </rpid:activities>%s</dm:person> \r \n "
" </presence> " , id ,
id , profile - > url , open , status , prpid ,
open , rpid , note ) ;
ct = " application/pidf+xml " ;
2007-12-18 01:12:50 +00:00
}
2008-02-14 17:28:58 +00:00
2007-12-15 00:39:53 +00:00
} else {
2008-02-14 17:28:58 +00:00
if ( in ) {
note = switch_mprintf ( " <dm:note>%s</dm:note> " , status ) ;
open = " open " ;
} else {
note = NULL ;
open = " closed " ;
}
2007-12-15 00:39:53 +00:00
pl = switch_mprintf ( " <?xml version='1.0' encoding='UTF-8'?> \r \n "
" <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 "
" <presentity uri= \" %s;method=SUBSCRIBE \" /> \r \n "
" <atom id= \" 1002 \" > \r \n "
" <address uri= \" %s \" priority= \" 0.800000 \" > \r \n "
" <status status= \" %s \" > \r \n "
" <note>%s</note> \r \n "
" </status> \r \n "
" <msnsubstatus substatus= \" %s \" /> \r \n "
" </address> \r \n "
" </atom> \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 "
" <rpid:activities> \r \n " " <rpid:%s/> \r \n "
" </rpid:activities>%s</dm:person> \r \n "
" </presence> " , id ,
id , profile - > url , open , status , prpid ,
open , rpid , note ) ;
2007-12-15 18:26:10 +00:00
ct = " application/pidf+xml " ;
2007-12-15 00:39:53 +00:00
}
2007-03-31 19:01:33 +00:00
2007-12-29 16:07:03 +00:00
switch_snprintf ( exp , sizeof ( exp ) , " active;expires=%ld " , ( long ) exptime ) ;
2007-03-31 19:01:33 +00:00
nua_notify ( nh ,
2007-12-15 00:39:53 +00:00
NUTAG_NEWSUB ( 1 ) ,
2007-12-29 16:07:03 +00:00
SIPTAG_SUBSCRIPTION_STATE_STR ( exp ) ,
2007-12-15 18:26:10 +00:00
SIPTAG_EVENT_STR ( event ) , SIPTAG_CONTENT_TYPE_STR ( ct ) , SIPTAG_PAYLOAD_STR ( pl ) , TAG_END ( ) ) ;
2007-03-31 19:01:33 +00:00
2007-10-24 23:20:47 +00:00
if ( done ) {
switch_core_hash_delete ( profile - > sub_hash , call_id ) ;
}
2007-12-18 01:12:50 +00:00
end :
2007-03-31 19:01:33 +00:00
switch_safe_free ( id ) ;
2007-12-15 18:26:10 +00:00
switch_safe_free ( clean_id ) ;
2007-03-31 19:01:33 +00:00
switch_safe_free ( note ) ;
switch_safe_free ( pl ) ;
switch_safe_free ( to ) ;
return 0 ;
}
2007-04-02 19:54:25 +00:00
static int sofia_presence_mwi_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
//char *proto = argv[0];
//char *user = argv[1];
2007-11-20 03:26:40 +00:00
//char *host = argv[2];
2007-04-02 19:54:25 +00:00
char * sub_to_user = argv [ 3 ] ;
char * sub_to_host = argv [ 4 ] ;
char * event = argv [ 5 ] ;
2007-10-28 16:07:23 +00:00
//char *contact = argv[6];
2007-04-02 19:54:25 +00:00
char * call_id = argv [ 7 ] ;
2007-10-24 23:20:47 +00:00
//char *full_from = argv[8];
//char *full_via = argv[9];
2007-04-02 19:54:25 +00:00
char * expires = argv [ 10 ] ;
2007-12-14 02:09:22 +00:00
char * body = argv [ 13 ] ;
2007-04-02 19:54:25 +00:00
char * exp ;
2007-04-29 01:16:49 +00:00
sofia_profile_t * profile = NULL ;
2007-10-28 16:07:23 +00:00
char * id = NULL ;
2007-04-02 19:54:25 +00:00
nua_handle_t * nh ;
2007-04-02 20:33:06 +00:00
int expire_sec = atoi ( expires ) ;
2007-12-13 23:30:16 +00:00
int * total = ( int * ) pArg ;
2007-12-14 00:00:57 +00:00
2007-04-02 19:54:25 +00:00
if ( ! ( profile = sofia_glue_find_profile ( sub_to_host ) ) ) {
2007-11-20 03:26:40 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot find profile for host %s \n " , sub_to_host ) ;
2007-04-02 19:54:25 +00:00
return 0 ;
}
2007-10-24 23:20:47 +00:00
if ( ! ( nh = ( nua_handle_t * ) switch_core_hash_find ( profile - > sub_hash , call_id ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot find handle for %s \n " , call_id ) ;
return 0 ;
}
2007-04-02 19:54:25 +00:00
id = switch_mprintf ( " sip:%s@%s " , sub_to_user , sub_to_host ) ;
2008-01-11 00:43:49 +00:00
expire_sec = ( int ) ( expire_sec - switch_timestamp ( NULL ) ) ;
2007-04-03 01:24:24 +00:00
if ( expire_sec < 0 ) {
expire_sec = 3600 ;
}
exp = switch_mprintf ( " active;expires=%ld " , expire_sec ) ;
2007-04-02 19:54:25 +00:00
nua_notify ( nh ,
2007-12-15 00:39:53 +00:00
NUTAG_NEWSUB ( 1 ) ,
2007-04-02 19:54:25 +00:00
SIPTAG_SUBSCRIPTION_STATE_STR ( exp ) ,
SIPTAG_EVENT_STR ( event ) , SIPTAG_CONTENT_TYPE_STR ( " application/simple-message-summary " ) , SIPTAG_PAYLOAD_STR ( body ) , TAG_END ( ) ) ;
2007-12-13 23:30:16 +00:00
2007-04-02 19:54:25 +00:00
switch_safe_free ( id ) ;
switch_safe_free ( exp ) ;
2007-04-29 01:16:49 +00:00
2007-12-13 23:30:16 +00:00
sofia_glue_release_profile ( profile ) ;
2007-12-14 00:00:57 +00:00
( * total ) + + ;
2007-12-13 23:30:16 +00:00
return 0 ;
}
static int sofia_presence_mwi_callback2 ( void * pArg , int argc , char * * argv , char * * columnNames )
{
2007-12-14 17:39:45 +00:00
char * sub_to_user = argv [ 0 ] ;
char * sub_to_host = argv [ 1 ] ;
2007-12-13 23:30:16 +00:00
char * event = " message-summary " ;
2007-12-14 17:39:45 +00:00
char * contact = argv [ 2 ] ;
char * body = argv [ 3 ] ;
2007-12-13 23:30:16 +00:00
sofia_profile_t * profile = NULL ;
char * id = NULL ;
nua_handle_t * nh ;
2007-12-14 17:39:45 +00:00
2007-12-14 00:00:57 +00:00
2007-12-13 23:30:16 +00:00
if ( ! ( profile = sofia_glue_find_profile ( sub_to_host ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot find profile for host %s \n " , sub_to_host ) ;
return 0 ;
}
id = switch_mprintf ( " sip:%s@%s " , sub_to_user , sub_to_host ) ;
2007-12-14 00:00:57 +00:00
2007-12-14 17:39:45 +00:00
contact = sofia_glue_get_url_from_contact ( contact , 0 ) ;
2007-12-13 23:30:16 +00:00
nh = nua_handle ( profile - > nua , NULL ,
2007-12-14 00:00:57 +00:00
NUTAG_URL ( contact ) ,
2007-12-13 23:30:16 +00:00
SIPTAG_FROM_STR ( id ) ,
2007-12-14 00:00:57 +00:00
SIPTAG_TO_STR ( id ) ,
SIPTAG_CONTACT_STR ( profile - > url ) ,
TAG_END ( ) ) ;
2007-12-13 23:30:16 +00:00
nua_notify ( nh ,
NUTAG_NEWSUB ( 1 ) ,
SIPTAG_EVENT_STR ( event ) , SIPTAG_CONTENT_TYPE_STR ( " application/simple-message-summary " ) , SIPTAG_PAYLOAD_STR ( body ) , TAG_END ( ) ) ;
switch_safe_free ( id ) ;
2007-12-14 00:00:57 +00:00
2007-05-03 01:55:25 +00:00
sofia_glue_release_profile ( profile ) ;
2007-12-14 00:00:57 +00:00
2007-04-02 19:54:25 +00:00
return 0 ;
}
2007-03-31 19:01:33 +00:00
void sofia_presence_handle_sip_i_subscribe ( int status ,
char const * phrase ,
2007-04-13 22:15:58 +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-31 19:01:33 +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 ;
2007-11-20 03:26:40 +00:00
const char * from_user = NULL , * from_host = NULL ;
const char * to_user = NULL , * to_host = NULL ;
char * my_to_user = NULL ;
2007-03-31 19:01:33 +00:00
char * sql , * event = NULL ;
char * proto = " sip " ;
char * d_user = NULL ;
char * contact_str = " " ;
2007-10-24 23:20:47 +00:00
const char * call_id = NULL ;
2007-03-31 19:01:33 +00:00
char * to_str = NULL ;
char * full_from = NULL ;
char * full_via = NULL ;
2007-12-14 02:09:22 +00:00
char * full_agent = NULL ;
2007-03-31 19:01:33 +00:00
char * sstr ;
const char * display = " \" user \" " ;
switch_event_t * sevent ;
2007-10-24 23:20:47 +00:00
int sub_state ;
2007-12-15 00:39:53 +00:00
int sent_reply = 0 ;
2007-10-24 23:20:47 +00:00
tl_gets ( tags ,
NUTAG_SUBSTATE_REF ( sub_state ) , TAG_END ( ) ) ;
2007-12-15 00:39:53 +00:00
event = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_event ) ;
2007-03-31 19:01:33 +00:00
if ( contact ) {
char * port = ( char * ) contact - > m_url - > url_port ;
2008-04-07 14:03:10 +00:00
char new_port [ 25 ] = " " ;
2007-03-31 19:01:33 +00:00
display = contact - > m_display ;
if ( switch_strlen_zero ( display ) ) {
if ( from ) {
display = from - > a_display ;
if ( switch_strlen_zero ( display ) ) {
display = " \" user \" " ;
}
}
} else {
display = " \" user \" " ;
}
2008-04-07 14:03:10 +00:00
if ( port ) {
switch_snprintf ( new_port , sizeof ( new_port ) , " :%s " , port ) ;
2007-03-31 19:01:33 +00:00
}
2008-04-07 14:03:10 +00:00
2007-03-31 19:01:33 +00:00
if ( contact - > m_url - > url_params ) {
2008-04-07 14:03:10 +00:00
contact_str = switch_mprintf ( " %s <sip:%s@%s%s;%s> " ,
display , contact - > m_url - > url_user , contact - > m_url - > url_host , new_port , contact - > m_url - > url_params ) ;
2007-03-31 19:01:33 +00:00
} else {
2008-04-07 14:03:10 +00:00
contact_str = switch_mprintf ( " %s <sip:%s@%s%s> " , display , contact - > m_url - > url_user , contact - > m_url - > url_host , new_port ) ;
2007-03-31 19:01:33 +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);
}
if ( to ) {
2007-11-20 03:26:40 +00:00
to_user = to - > a_url - > url_user ;
to_host = to - > a_url - > url_host ;
2007-03-31 19:01:33 +00:00
}
2007-10-24 23:20:47 +00:00
if ( sip & & sip - > sip_from ) {
2007-11-20 03:26:40 +00:00
from_user = sip - > sip_from - > a_url - > url_user ;
from_host = sip - > sip_from - > a_url - > url_host ;
2007-10-24 23:20:47 +00:00
} else {
from_user = " n/a " ;
from_host = " n/a " ;
}
2007-03-31 19:01:33 +00:00
2007-12-13 04:01:29 +00:00
if ( to_user & & ( strstr ( to_user , " ext+ " ) | | strstr ( to_user , " user+ " ) ) ) {
char protocol [ 80 ] ;
2007-03-31 19:01:33 +00:00
char * p ;
2007-12-13 04:01:29 +00:00
switch_copy_string ( protocol , to_user , sizeof ( protocol ) ) ;
if ( ( p = strchr ( protocol , ' + ' ) ) ) {
2007-03-31 19:01:33 +00:00
* p = ' \0 ' ;
}
2007-10-24 23:20:47 +00:00
2007-03-31 19:01:33 +00:00
if ( switch_event_create ( & sevent , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
2007-12-13 04:01:29 +00:00
switch_event_add_header ( sevent , SWITCH_STACK_BOTTOM , " proto " , protocol ) ;
2007-03-31 19:01:33 +00:00
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 ) ;
2007-10-24 23:20:47 +00:00
switch_event_add_header ( sevent , SWITCH_STACK_BOTTOM , " rpid " , " active " ) ;
2007-03-31 19:01:33 +00:00
switch_event_add_header ( sevent , SWITCH_STACK_BOTTOM , " status " , " Click To Call " ) ;
switch_event_fire ( & sevent ) ;
}
2007-10-24 23:20:47 +00:00
} else {
if ( switch_event_create ( & sevent , SWITCH_EVENT_PRESENCE_PROBE ) = = 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 " , from_user , from_host ) ;
switch_event_add_header ( sevent , SWITCH_STACK_BOTTOM , " to " , " %s@%s " , to_user , to_host ) ;
2007-12-15 00:39:53 +00:00
switch_event_add_header ( sevent , SWITCH_STACK_BOTTOM , " proto-specific-event-name " , " %s " , event ) ;
2007-10-24 23:20:47 +00:00
switch_event_fire ( & sevent ) ;
}
2007-03-31 19:01:33 +00:00
}
2007-12-13 04:01:29 +00:00
if ( to_user & & strchr ( to_user , ' + ' ) ) {
2007-03-31 19:01:33 +00:00
char * h ;
if ( ( proto = ( d_user = strdup ( to_user ) ) ) ) {
2007-11-20 03:26:40 +00:00
if ( ( my_to_user = strchr ( d_user , ' + ' ) ) ) {
* my_to_user + + = ' \0 ' ;
to_user = my_to_user ;
2007-03-31 19:01:33 +00:00
if ( ( h = strchr ( to_user , ' + ' ) ) | | ( h = strchr ( to_user , ' @ ' ) ) ) {
* h + + = ' \0 ' ;
to_host = h ;
}
}
}
if ( ! ( proto & & to_user & & to_host ) ) {
nua_respond ( nh , SIP_404_NOT_FOUND , NUTAG_WITH_THIS ( nua ) , TAG_END ( ) ) ;
goto end ;
}
}
2007-11-20 03:26:40 +00:00
call_id = sip - > sip_call_id - > i_id ;
2007-03-31 19:01:33 +00:00
full_from = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_from ) ;
full_via = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_via ) ;
exp_raw = ( sip - > sip_expires ? sip - > sip_expires - > ex_delta : 3600 ) ;
2008-01-11 00:43:49 +00:00
exp = ( long ) switch_timestamp ( NULL ) + exp_raw ;
2007-03-31 19:01:33 +00:00
2008-03-05 20:31:18 +00:00
if ( sofia_test_pflag ( profile , PFLAG_MULTIREG ) ) {
sql = switch_mprintf ( " delete from sip_subscriptions where call_id='%q' " , call_id ) ;
} else {
sql = switch_mprintf ( " delete from sip_subscriptions where "
" proto='%q' and sip_user='%q' and sip_host='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q' " ,
proto ,
from_user ,
from_host ,
to_user ,
to_host , event
) ;
}
2007-04-04 03:08:17 +00:00
2008-03-05 20:31:18 +00:00
switch_mutex_lock ( profile - > ireg_mutex ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( sql ! = NULL ) ;
2008-03-05 20:31:18 +00:00
sofia_glue_execute_sql ( profile , & sql , SWITCH_TRUE ) ;
2007-03-31 19:01:33 +00:00
2007-10-24 23:20:47 +00:00
if ( sub_state = = nua_substate_terminated ) {
sstr = switch_mprintf ( " terminated " ) ;
switch_core_hash_delete ( profile - > sub_hash , call_id ) ;
} else {
2008-02-14 17:28:58 +00:00
sip_accept_t * ap = sip - > sip_accept ;
char accept [ 256 ] = " " ;
2007-12-14 02:09:22 +00:00
full_agent = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_user_agent ) ;
2008-02-14 17:28:58 +00:00
while ( ap ) {
switch_snprintf ( accept + strlen ( accept ) , sizeof ( accept ) - strlen ( accept ) , " %s%s " , ap - > ac_type , ap - > ac_next ? " , " : " " ) ;
ap = ap - > ac_next ;
}
2007-12-14 02:09:22 +00:00
sql = switch_mprintf ( " insert into sip_subscriptions values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld,'%q','%q') " ,
proto , from_user , from_host , to_user , to_host , event ,
2008-02-14 17:28:58 +00:00
contact_str , call_id , full_from , full_via , exp , full_agent , accept ) ;
2007-10-24 23:20:47 +00:00
2007-12-12 23:21:45 +00:00
switch_assert ( sql ! = NULL ) ;
2008-03-05 20:31:18 +00:00
sofia_glue_execute_sql ( profile , & sql , SWITCH_TRUE ) ;
2007-10-24 23:20:47 +00:00
sstr = switch_mprintf ( " active;expires=%ld " , exp_raw ) ;
2007-12-15 00:39:53 +00:00
if ( status < 200 ) {
switch_core_hash_insert ( profile - > sub_hash , call_id , nh ) ;
}
2007-10-24 23:20:47 +00:00
}
2007-12-15 00:39:53 +00:00
2007-12-30 23:25:45 +00:00
switch_mutex_unlock ( profile - > ireg_mutex ) ;
2007-12-15 00:39:53 +00:00
if ( status < 200 ) {
nua_respond ( nh , SIP_202_ACCEPTED ,
NUTAG_WITH_THIS ( nua ) ,
SIPTAG_SUBSCRIPTION_STATE_STR ( sstr ) ,
2007-12-29 02:15:54 +00:00
//SIPTAG_FROM(sip->sip_to),
//SIPTAG_TO(sip->sip_from),
//SIPTAG_CONTACT_STR(contact_str),
2007-12-15 00:39:53 +00:00
TAG_END ( ) ) ;
}
sent_reply + + ;
#if 0
nua_notify ( nh ,
NUTAG_NEWSUB ( 1 ) ,
SIPTAG_SUBSCRIPTION_STATE_STR ( sstr ) , SIPTAG_EVENT_STR ( event ) ,
SIPTAG_CONTENT_TYPE_STR ( " application/simple-message-summary " ) ,
SIPTAG_PAYLOAD_STR ( " Note: Come to ClueCon http://www.cluecon.com \n \n " ) ,
2007-12-14 00:29:17 +00:00
TAG_END ( ) ) ;
2007-12-15 00:39:53 +00:00
# endif
2007-07-02 20:17:10 +00:00
2007-03-31 19:01:33 +00:00
switch_safe_free ( sstr ) ;
2007-11-17 04:10:35 +00:00
if ( ( sql = switch_mprintf ( " select * from sip_subscriptions where sip_user='%q' and sip_host='%q' " , to_user , to_host ) ) ) {
2007-04-04 03:08:17 +00:00
sofia_glue_execute_sql_callback ( profile ,
SWITCH_FALSE ,
profile - > ireg_mutex ,
sql ,
sofia_presence_sub_reg_callback ,
profile ) ;
2007-03-31 19:01:33 +00:00
switch_safe_free ( sql ) ;
}
2007-04-04 03:08:17 +00:00
end :
2007-03-31 19:01:33 +00:00
if ( event ) {
su_free ( profile - > home , event ) ;
}
2007-10-24 23:20:47 +00:00
2007-03-31 19:01:33 +00:00
if ( full_from ) {
su_free ( profile - > home , full_from ) ;
}
if ( full_via ) {
su_free ( profile - > home , full_via ) ;
}
2007-12-14 02:09:22 +00:00
if ( full_agent ) {
su_free ( profile - > home , full_agent ) ;
}
2007-03-31 19:01:33 +00:00
switch_safe_free ( d_user ) ;
switch_safe_free ( to_str ) ;
switch_safe_free ( contact_str ) ;
2007-12-15 00:39:53 +00:00
if ( ! sent_reply ) {
nua_respond ( nh , 481 , " INVALID SUBSCRIPTION " , TAG_END ( ) ) ;
}
2007-03-31 19:01:33 +00:00
}
2007-12-15 00:39:53 +00:00
2007-03-31 19:01:33 +00:00
}
void sofia_presence_handle_sip_r_subscribe ( int status ,
char const * phrase ,
2007-04-13 22:15:58 +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-31 19:01:33 +00:00
{
}
2007-04-13 22:15:58 +00:00
void sofia_presence_handle_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 [ ] )
2007-03-31 19:01:33 +00:00
{
if ( sip ) {
sip_from_t const * from = sip - > sip_from ;
char * from_user = NULL ;
char * from_host = NULL ;
char * rpid = " unknown " ;
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 ) {
switch_xml_t xml , note , person , tuple , status , basic , act ;
switch_event_t * event ;
uint8_t in = 0 ;
char * sql ;
if ( ( xml = switch_xml_parse_str ( payload - > pl_data , strlen ( payload - > pl_data ) ) ) ) {
char * status_txt = " " , * note_txt = " " ;
if ( ( tuple = switch_xml_child ( xml , " tuple " ) ) & & ( status = switch_xml_child ( tuple , " status " ) )
& & ( basic = switch_xml_child ( status , " basic " ) ) ) {
status_txt = basic - > txt ;
}
if ( ( person = switch_xml_child ( xml , " dm:person " ) ) & & ( note = switch_xml_child ( person , " dm:note " ) ) ) {
note_txt = note - > txt ;
}
if ( person & & ( act = switch_xml_child ( person , " rpid:activities " ) ) ) {
if ( ( rpid = strchr ( act - > child - > name , ' : ' ) ) ) {
rpid + + ;
} else {
rpid = act - > child - > name ;
}
}
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 " ;
}
}
if ( ( sql =
2007-11-15 16:55:46 +00:00
switch_mprintf ( " update sip_registrations set status='%q',rpid='%q' where sip_user='%q' and sip_host='%q' " ,
2007-03-31 19:01:33 +00:00
note_txt , rpid , from_user , from_host ) ) ) {
2008-03-05 20:31:18 +00:00
sofia_glue_execute_sql ( profile , & sql , SWITCH_TRUE ) ;
2007-03-31 19:01:33 +00:00
}
event_type = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_event ) ;
if ( in ) {
if ( switch_event_create ( & event , SWITCH_EVENT_PRESENCE_IN ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " rpid " , " %s " , rpid ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " login " , " %s " , profile - > url ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , from_user , from_host ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " status " , " %s " , note_txt ) ;
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 ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " rpid " , " %s " , rpid ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " login " , " %s " , profile - > url ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " from " , " %s@%s " , from_user , from_host ) ;
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 ) ;
}
switch_xml_free ( xml ) ;
}
}
}
nua_respond ( nh , SIP_200_OK , NUTAG_WITH_THIS ( nua ) , TAG_END ( ) ) ;
}
void sofia_presence_set_hash_key ( char * hash_key , int32_t len , sip_t const * sip )
{
2007-11-20 03:26:40 +00:00
url_t * to = sip - > sip_to - > a_url ;
url_t * from = sip - > sip_from - > a_url ;
2007-12-12 21:53:32 +00:00
switch_snprintf ( hash_key , len , " %s%s%s " , from - > url_user , from - > url_host , to - > url_user ) ;
2007-03-31 19:01:33 +00:00
}
void sofia_presence_handle_sip_i_message ( int status ,
char const * phrase ,
2007-04-13 22:15:58 +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-31 19:01:33 +00:00
{
if ( sip ) {
sip_from_t const * from = sip - > sip_from ;
2007-11-20 03:26:40 +00:00
const char * from_user = NULL ;
const char * from_host = NULL ;
2007-03-31 19:01:33 +00:00
sip_to_t const * to = sip - > sip_to ;
2007-11-20 03:26:40 +00:00
const char * to_user = NULL ;
const char * to_host = NULL ;
2007-03-31 19:01:33 +00:00
sip_subject_t const * sip_subject = sip - > sip_subject ;
sip_payload_t * payload = sip - > sip_payload ;
const char * subject = " n/a " ;
char * msg = NULL ;
2007-12-30 01:43:57 +00:00
if ( sip - > sip_content_type & & sip - > sip_content_type - > c_subtype ) {
2007-11-20 03:26:40 +00:00
if ( strstr ( sip - > sip_content_type - > c_subtype , " composing " ) ) {
2007-03-31 19:01:33 +00:00
return ;
}
}
if ( from ) {
2007-11-20 03:26:40 +00:00
from_user = from - > a_url - > url_user ;
from_host = from - > a_url - > url_host ;
2007-03-31 19:01:33 +00:00
}
if ( to ) {
2007-11-20 03:26:40 +00:00
to_user = to - > a_url - > url_user ;
to_host = to - > a_url - > url_host ;
2007-03-31 19:01:33 +00:00
}
if ( ! to_user ) {
return ;
}
if ( payload ) {
msg = payload - > pl_data ;
}
if ( sip_subject ) {
subject = sip_subject - > g_value ;
}
if ( nh ) {
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 ;
char * full_from ;
char proto [ 512 ] = SOFIA_CHAT_PROTO ;
full_from = sip_header_as_string ( profile - > home , ( void * ) sip - > sip_from ) ;
if ( ( p = strchr ( to_user , ' + ' ) ) ) {
switch_copy_string ( proto , to_user , sizeof ( proto ) ) ;
p = strchr ( proto , ' + ' ) ;
* p + + = ' \0 ' ;
if ( ( to_addr = strdup ( p ) ) ) {
if ( ( p = strchr ( to_addr , ' + ' ) ) ) {
* p = ' @ ' ;
}
}
} else {
to_addr = switch_mprintf ( " %s@%s " , to_user , to_host ) ;
}
from_addr = switch_mprintf ( " %s@%s " , from_user , from_host ) ;
sofia_presence_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 ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " proto " , SOFIA_CHAT_PROTO ) ;
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 ) {
switch_event_add_body ( event , " %s " , msg ) ;
}
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 {
switch_chat_interface_t * ci ;
if ( ( ci = switch_loadable_module_get_chat_interface ( proto ) ) ) {
ci - > chat_send ( SOFIA_CHAT_PROTO , from_addr , to_addr , " " , msg , full_from ) ;
} else {
2007-08-03 21:29:01 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Chat Interface [%s]! \n " , proto ) ;
2007-03-31 19:01:33 +00:00
}
}
switch_safe_free ( to_addr ) ;
switch_safe_free ( from_addr ) ;
if ( full_from ) {
su_free ( profile - > home , full_from ) ;
}
}
}
}
2007-04-13 22:15:58 +00:00
void sofia_presence_set_chat_hash ( private_object_t * tech_pvt , sip_t const * sip )
2007-03-31 19:01:33 +00:00
{
char hash_key [ 256 ] = " " ;
char buf [ 512 ] ;
2007-09-29 01:06:08 +00:00
su_home_t * home = NULL ;
2007-03-31 19:01:33 +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 ) {
return ;
}
if ( sofia_reg_find_reg_url ( tech_pvt - > profile , sip - > sip_from - > a_url - > url_user , sip - > sip_from - > a_url - > url_host , buf , sizeof ( buf ) ) ) {
2007-09-29 01:06:08 +00:00
home = su_home_new ( sizeof ( * home ) ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( home ! = NULL ) ;
2007-09-29 01:06:08 +00:00
tech_pvt - > chat_from = sip_header_as_string ( home , ( const sip_header_t * ) sip - > sip_to ) ;
2007-03-31 19:01:33 +00:00
tech_pvt - > chat_to = switch_core_session_strdup ( tech_pvt - > session , buf ) ;
sofia_presence_set_hash_key ( hash_key , sizeof ( hash_key ) , sip ) ;
2007-09-29 01:06:08 +00:00
su_home_unref ( home ) ;
home = NULL ;
2007-03-31 19:01:33 +00:00
} 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 ) ;
}
2007-11-17 04:10:35 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2008-02-03 22:14:57 +00:00
* indent - tabs - mode : t
2007-11-17 04:10:35 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 expandtab :
*/