2017-01-06 02:10:15 -05:00
/*
2016-10-05 11:05:32 -04:00
* Freeswitch Modular Media Switching Software Library / Soft - Switch Application
2014-06-11 12:48:46 -05:00
* Copyright ( C ) 2005 - 2014 , Anthony Minessale II < anthm @ freeswitch . org >
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II < anthm @ freeswitch . org >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
2017-01-06 02:10:15 -05:00
*
2014-06-11 12:48:46 -05:00
* Anthony Minessale II < anthm @ freeswitch . org >
2014-09-06 12:06:24 +08:00
* Seven Du < dujinfang @ gmail . com >
2014-06-11 12:48:46 -05:00
*
* mod_verto . c - - HTML5 Verto interface
*
*/
# include <switch.h>
# include <switch_json.h>
2018-12-12 01:33:06 +04:00
# include <switch_stun.h>
2014-06-11 12:48:46 -05:00
/* Prototypes */
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_verto_shutdown ) ;
SWITCH_MODULE_LOAD_FUNCTION ( mod_verto_load ) ;
SWITCH_MODULE_RUNTIME_FUNCTION ( mod_verto_runtime ) ;
SWITCH_MODULE_DEFINITION ( mod_verto , mod_verto_load , mod_verto_shutdown , mod_verto_runtime ) ;
2020-03-25 03:49:19 +04:00
# define HTTP_CHUNK_SIZE 1024 * 32
2014-06-11 12:48:46 -05:00
# define EP_NAME "verto.rtc"
2017-04-17 16:33:33 -05:00
//#define WSS_STANDALONE 1
2023-05-30 22:45:54 +03:00
# include "libks/ks.h"
2014-06-11 12:48:46 -05:00
# include <mod_verto.h>
2014-10-18 09:53:57 +02:00
# ifndef WIN32
2014-06-11 12:48:46 -05:00
# include <sys/param.h>
2014-10-18 09:53:57 +02:00
# endif
2014-06-11 12:48:46 -05:00
# include <sys/stat.h>
# include <fcntl.h>
2014-10-18 09:53:57 +02:00
# ifndef WIN32
2014-06-11 12:48:46 -05:00
# include <sys/file.h>
2014-10-18 09:53:57 +02:00
# endif
2014-06-11 12:48:46 -05:00
# include <ctype.h>
# include <sys/stat.h>
2018-09-13 00:14:20 +03:00
# ifdef WIN32
# define strerror_r(errno, buf, len) strerror_s(buf, len, errno)
# endif
2014-06-11 12:48:46 -05:00
2018-10-18 04:52:14 -07:00
# define log_and_exit(severity, ...) switch_log_printf(SWITCH_CHANNEL_LOG, (severity), __VA_ARGS__); goto error
# define die(...) log_and_exit(SWITCH_LOG_WARNING, __VA_ARGS__)
2018-08-31 08:09:49 -07:00
# define die_errno(fmt) do { char errbuf[BUFSIZ] = {0}; strerror_r(errno, (char *)&errbuf, sizeof(errbuf)); die(fmt ", errno=%d, %s\n", errno, (char *)&errbuf); } while(0)
2018-09-06 04:18:28 -07:00
# define die_errnof(fmt, ...) do { char errbuf[BUFSIZ] = {0}; strerror_r(errno, (char *)&errbuf, sizeof(errbuf)); die(fmt ", errno=%d, %s\n", __VA_ARGS__, errno, (char *)&errbuf); } while(0)
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
static struct globals_s verto_globals ;
2014-06-11 12:48:46 -05:00
static struct {
switch_mutex_t * store_mutex ;
switch_hash_t * store_hash ;
} json_GLOBALS ;
const char json_sql [ ] =
" create table json_store ( \n "
" name varchar(255) not null, \n "
" data text \n "
" ); \n " ;
typedef enum {
CMD_ADD ,
CMD_DEL ,
CMD_DUMP ,
CMD_COMMIT ,
CMD_RETRIEVE
} store_cmd_t ;
typedef struct {
switch_mutex_t * mutex ;
cJSON * JSON_STORE ;
} json_store_t ;
static void json_cleanup ( void )
{
switch_hash_index_t * hi = NULL ;
void * val ;
const void * var ;
cJSON * json ;
2014-06-13 03:02:09 -04:00
if ( ! json_GLOBALS . store_hash ) {
return ;
}
2014-06-11 12:48:46 -05:00
switch_mutex_lock ( json_GLOBALS . store_mutex ) ;
top :
2014-12-22 15:09:50 -06:00
for ( hi = switch_core_hash_first_iter ( json_GLOBALS . store_hash , hi ) ; hi ; ) {
2014-06-11 12:48:46 -05:00
switch_core_hash_this ( hi , & var , NULL , & val ) ;
json = ( cJSON * ) val ;
cJSON_Delete ( json ) ;
switch_core_hash_delete ( json_GLOBALS . store_hash , var ) ;
goto top ;
}
switch_safe_free ( hi ) ;
switch_mutex_unlock ( json_GLOBALS . store_mutex ) ;
}
static switch_bool_t check_name ( const char * name )
{
const char * p ;
for ( p = name ; p & & * p ; p + + ) {
if ( ( * p > = ' A ' & & * p < = ' Z ' ) | | ( * p > = ' a ' & & * p < = ' z ' ) | | ( * p > = ' 0 ' & & * p < = ' 9 ' ) | | * p = = ' - ' | | * p = = ' _ ' ) continue ;
return SWITCH_FALSE ;
}
return SWITCH_TRUE ;
}
2016-07-10 22:25:14 -05:00
static switch_status_t verto_read_text_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id ) ;
static switch_status_t verto_write_text_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id ) ;
static void set_text_funcs ( switch_core_session_t * session ) ;
2014-06-11 12:48:46 -05:00
static verto_profile_t * find_profile ( const char * name ) ;
static jsock_t * get_jsock ( const char * uuid ) ;
static void verto_deinit_ssl ( verto_profile_t * profile )
{
if ( profile - > ssl_ctx ) {
SSL_CTX_free ( profile - > ssl_ctx ) ;
profile - > ssl_ctx = NULL ;
}
}
2020-03-25 03:49:19 +04:00
static void close_file ( ks_socket_t * sock )
2014-09-17 02:14:43 +05:00
{
2020-03-25 03:49:19 +04:00
if ( * sock ! = KS_SOCK_INVALID ) {
2014-10-18 09:53:57 +02:00
# ifndef WIN32
2014-09-17 02:14:43 +05:00
close ( * sock ) ;
2014-10-18 09:53:57 +02:00
# else
closesocket ( * sock ) ;
# endif
2020-03-25 03:49:19 +04:00
* sock = KS_SOCK_INVALID ;
2014-09-17 02:14:43 +05:00
}
}
2020-03-25 03:49:19 +04:00
static void close_socket ( ks_socket_t * sock )
2014-09-17 02:14:43 +05:00
{
2020-03-25 03:49:19 +04:00
if ( * sock ! = KS_SOCK_INVALID ) {
2014-09-17 02:14:43 +05:00
shutdown ( * sock , 2 ) ;
close_file ( sock ) ;
}
}
2019-05-16 15:25:10 +01:00
void verto_broadcast ( const char * event_channel , cJSON * json , const char * key , switch_event_channel_id_t id , void * user_data ) ;
2014-06-11 12:48:46 -05:00
2017-01-06 02:10:15 -05:00
static int verto_init_ssl ( verto_profile_t * profile )
2014-06-11 12:48:46 -05:00
{
2014-09-17 02:14:43 +05:00
const char * err = " " ;
int i = 0 ;
2014-06-11 12:48:46 -05:00
profile - > ssl_method = SSLv23_server_method ( ) ; /* create server instance */
profile - > ssl_ctx = SSL_CTX_new ( profile - > ssl_method ) ; /* create context */
profile - > ssl_ready = 1 ;
assert ( profile - > ssl_ctx ) ;
2014-07-18 09:10:15 -05:00
/* Disable SSLv2 */
SSL_CTX_set_options ( profile - > ssl_ctx , SSL_OP_NO_SSLv2 ) ;
/* Disable SSLv3 */
SSL_CTX_set_options ( profile - > ssl_ctx , SSL_OP_NO_SSLv3 ) ;
/* Disable TLSv1 */
SSL_CTX_set_options ( profile - > ssl_ctx , SSL_OP_NO_TLSv1 ) ;
/* Disable Compression CRIME (Compression Ratio Info-leak Made Easy) */
SSL_CTX_set_options ( profile - > ssl_ctx , SSL_OP_NO_COMPRESSION ) ;
2014-06-11 12:48:46 -05:00
/* set the local certificate from CertFile */
if ( ! zstr ( profile - > chain ) ) {
2014-09-17 02:14:43 +05:00
if ( switch_file_exists ( profile - > chain , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
err = " SUPPLIED CHAIN FILE NOT FOUND \n " ;
goto fail ;
}
if ( ! SSL_CTX_use_certificate_chain_file ( profile - > ssl_ctx , profile - > chain ) ) {
err = " CERT CHAIN FILE ERROR " ;
goto fail ;
}
}
if ( switch_file_exists ( profile - > cert , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
err = " SUPPLIED CERT FILE NOT FOUND \n " ;
goto fail ;
2014-06-11 12:48:46 -05:00
}
2014-09-17 02:14:43 +05:00
if ( ! SSL_CTX_use_certificate_file ( profile - > ssl_ctx , profile - > cert , SSL_FILETYPE_PEM ) ) {
err = " CERT FILE ERROR " ;
goto fail ;
}
2014-06-11 12:48:46 -05:00
/* set the private key from KeyFile */
2014-09-17 02:14:43 +05:00
if ( switch_file_exists ( profile - > key , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
err = " SUPPLIED KEY FILE NOT FOUND \n " ;
goto fail ;
}
if ( ! SSL_CTX_use_PrivateKey_file ( profile - > ssl_ctx , profile - > key , SSL_FILETYPE_PEM ) ) {
err = " PRIVATE KEY FILE ERROR " ;
goto fail ;
}
2014-06-11 12:48:46 -05:00
/* verify private key */
if ( ! SSL_CTX_check_private_key ( profile - > ssl_ctx ) ) {
2014-09-17 02:14:43 +05:00
err = " PRIVATE KEY FILE ERROR " ;
goto fail ;
}
SSL_CTX_set_cipher_list ( profile - > ssl_ctx , " HIGH:!DSS:!aNULL@STRENGTH " ) ;
return 1 ;
fail :
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " SSL ERR: %s \n " , err ) ;
profile - > ssl_ready = 0 ;
verto_deinit_ssl ( profile ) ;
for ( i = 0 ; i < profile - > i ; i + + ) {
if ( profile - > ip [ i ] . secure ) {
2017-01-06 02:10:15 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " SSL NOT ENABLED FOR LISTENER %s:%d. REVERTING TO WS \n " ,
2014-09-17 02:14:43 +05:00
profile - > ip [ i ] . local_ip , profile - > ip [ i ] . local_port ) ;
profile - > ip [ i ] . secure = 0 ;
}
2014-06-11 12:48:46 -05:00
}
2014-09-17 02:14:43 +05:00
return 0 ;
2014-06-11 12:48:46 -05:00
}
struct jsock_sub_node_head_s ;
typedef struct jsock_sub_node_s {
jsock_t * jsock ;
2014-06-20 19:21:56 +05:00
uint32_t serno ;
2014-06-11 12:48:46 -05:00
struct jsock_sub_node_head_s * head ;
struct jsock_sub_node_s * next ;
} jsock_sub_node_t ;
typedef struct jsock_sub_node_head_s {
jsock_sub_node_t * node ;
jsock_sub_node_t * tail ;
char * event_channel ;
} jsock_sub_node_head_t ;
static uint32_t jsock_unsub_head ( jsock_t * jsock , jsock_sub_node_head_t * head )
{
uint32_t x = 0 ;
jsock_sub_node_t * thisnp = NULL , * np , * last = NULL ;
np = head - > tail = head - > node ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
while ( np ) {
thisnp = np ;
np = np - > next ;
if ( ! jsock | | thisnp - > jsock = = jsock ) {
x + + ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( last ) {
last - > next = np ;
} else {
head - > node = np ;
}
2017-02-09 17:23:30 -06:00
if ( thisnp - > jsock - > profile - > debug | | verto_globals . debug ) {
2020-04-01 00:31:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , verto_globals . debug_level , " UNSUBBING %s [%s] \n " , thisnp - > jsock - > name , thisnp - > head - > event_channel ) ;
2014-06-11 12:48:46 -05:00
}
thisnp - > jsock = NULL ;
free ( thisnp ) ;
} else {
last = thisnp ;
head - > tail = last ;
}
}
return x ;
}
2015-01-05 21:14:35 -06:00
static void detach_calls ( jsock_t * jsock ) ;
2014-06-11 12:48:46 -05:00
static void unsub_all_jsock ( void )
{
switch_hash_index_t * hi ;
void * val ;
jsock_sub_node_head_t * head ;
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_wrlock ( verto_globals . event_channel_rwlock ) ;
2014-06-11 12:48:46 -05:00
top :
head = NULL ;
2017-02-09 17:23:30 -06:00
for ( hi = switch_core_hash_first ( verto_globals . event_channel_hash ) ; hi ; ) {
2014-06-11 12:48:46 -05:00
switch_core_hash_this ( hi , NULL , NULL , & val ) ;
head = ( jsock_sub_node_head_t * ) val ;
jsock_unsub_head ( NULL , head ) ;
2017-02-09 17:23:30 -06:00
switch_core_hash_delete ( verto_globals . event_channel_hash , head - > event_channel ) ;
2014-06-11 12:48:46 -05:00
free ( head - > event_channel ) ;
free ( head ) ;
switch_safe_free ( hi ) ;
goto top ;
}
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_unlock ( verto_globals . event_channel_rwlock ) ;
2014-06-11 12:48:46 -05:00
}
static uint32_t jsock_unsub_channel ( jsock_t * jsock , const char * event_channel )
{
jsock_sub_node_head_t * head ;
uint32_t x = 0 ;
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_wrlock ( verto_globals . event_channel_rwlock ) ;
2014-06-11 12:48:46 -05:00
if ( ! event_channel ) {
switch_hash_index_t * hi ;
void * val ;
2017-02-09 17:23:30 -06:00
for ( hi = switch_core_hash_first ( verto_globals . event_channel_hash ) ; hi ; hi = switch_core_hash_next ( & hi ) ) {
2014-06-11 12:48:46 -05:00
switch_core_hash_this ( hi , NULL , NULL , & val ) ;
if ( val ) {
head = ( jsock_sub_node_head_t * ) val ;
x + = jsock_unsub_head ( jsock , head ) ;
}
}
} else {
2017-02-09 17:23:30 -06:00
if ( ( head = switch_core_hash_find ( verto_globals . event_channel_hash , event_channel ) ) ) {
2014-06-11 12:48:46 -05:00
x + = jsock_unsub_head ( jsock , head ) ;
}
}
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_unlock ( verto_globals . event_channel_rwlock ) ;
2014-06-11 12:48:46 -05:00
return x ;
}
static void presence_ping ( const char * event_channel )
{
switch_console_callback_match_t * matches ;
const char * val = event_channel ;
if ( val ) {
if ( ! strcasecmp ( val , " presence " ) ) {
val = NULL ;
} else {
char * p ;
if ( ( p = strchr ( val , ' . ' ) ) ) {
val = ( p + 1 ) ;
}
}
}
if ( ( matches = switch_core_session_findall_matching_var ( " presence_id " , val ) ) ) {
switch_console_callback_match_node_t * m ;
switch_core_session_t * session ;
for ( m = matches - > head ; m ; m = m - > next ) {
if ( ( session = switch_core_session_locate ( m - > val ) ) ) {
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
switch_event_t * event ;
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_CALLSTATE ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_callstate_t callstate = switch_channel_get_callstate ( channel ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Original-Channel-Call-State " , switch_channel_callstate2str ( callstate ) ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Channel-Call-State-Number " , " %d " , callstate ) ;
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_core_session_rwunlock ( session ) ;
}
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_console_free_matches ( & matches ) ;
}
}
static switch_status_t jsock_sub_channel ( jsock_t * jsock , const char * event_channel )
{
jsock_sub_node_t * node , * np ;
jsock_sub_node_head_t * head ;
switch_status_t status = SWITCH_STATUS_FALSE ;
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_wrlock ( verto_globals . event_channel_rwlock ) ;
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
if ( ! ( head = switch_core_hash_find ( verto_globals . event_channel_hash , event_channel ) ) ) {
2014-06-11 12:48:46 -05:00
switch_zmalloc ( head , sizeof ( * head ) ) ;
head - > event_channel = strdup ( event_channel ) ;
2017-02-09 17:23:30 -06:00
switch_core_hash_insert ( verto_globals . event_channel_hash , event_channel , head ) ;
2014-06-11 12:48:46 -05:00
switch_zmalloc ( node , sizeof ( * node ) ) ;
node - > jsock = jsock ;
node - > head = head ;
head - > node = node ;
head - > tail = node ;
status = SWITCH_STATUS_SUCCESS ;
} else {
int exist = 0 ;
for ( np = head - > node ; np ; np = np - > next ) {
if ( np - > jsock = = jsock ) {
exist = 1 ;
break ;
}
}
if ( ! exist ) {
switch_zmalloc ( node , sizeof ( * node ) ) ;
node - > jsock = jsock ;
node - > head = head ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! head - > node ) {
head - > node = node ;
head - > tail = node ;
} else {
head - > tail - > next = node ;
head - > tail = head - > tail - > next ;
}
status = SWITCH_STATUS_SUCCESS ;
}
}
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_unlock ( verto_globals . event_channel_rwlock ) ;
2014-06-11 12:48:46 -05:00
if ( status = = SWITCH_STATUS_SUCCESS & & ! strncasecmp ( event_channel , " presence " , 8 ) ) {
presence_ping ( event_channel ) ;
}
return status ;
}
static uint32_t ID = 1 ;
static void del_jsock ( jsock_t * jsock )
{
jsock_t * p , * last = NULL ;
jsock_unsub_channel ( jsock , NULL ) ;
switch_event_channel_permission_clear ( jsock - > uuid_str ) ;
switch_mutex_lock ( jsock - > profile - > mutex ) ;
for ( p = jsock - > profile - > jsock_head ; p ; p = p - > next ) {
if ( p = = jsock ) {
if ( last ) {
last - > next = p - > next ;
} else {
jsock - > profile - > jsock_head = p - > next ;
}
jsock - > profile - > jsock_count - - ;
break ;
}
last = p ;
}
switch_mutex_unlock ( jsock - > profile - > mutex ) ;
}
static void add_jsock ( jsock_t * jsock )
{
switch_mutex_lock ( jsock - > profile - > mutex ) ;
jsock - > next = jsock - > profile - > jsock_head ;
jsock - > profile - > jsock_head = jsock ;
jsock - > profile - > jsock_count + + ;
switch_mutex_unlock ( jsock - > profile - > mutex ) ;
}
static uint32_t next_id ( void )
{
uint32_t id ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
id = ID + + ;
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
return id ;
}
static cJSON * jrpc_new ( uint32_t id )
{
cJSON * obj = cJSON_CreateObject ( ) ;
cJSON_AddItemToObject ( obj , " jsonrpc " , cJSON_CreateString ( " 2.0 " ) ) ;
if ( id ) {
cJSON_AddItemToObject ( obj , " id " , cJSON_CreateNumber ( id ) ) ;
}
return obj ;
}
static cJSON * jrpc_new_req ( const char * method , const char * call_id , cJSON * * paramsP )
{
cJSON * msg , * params = NULL ;
uint32_t id = next_id ( ) ;
msg = jrpc_new ( id ) ;
if ( paramsP & & * paramsP ) {
params = * paramsP ;
}
if ( ! params ) {
params = cJSON_CreateObject ( ) ;
}
cJSON_AddItemToObject ( msg , " method " , cJSON_CreateString ( method ) ) ;
cJSON_AddItemToObject ( msg , " params " , params ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( call_id ) {
cJSON_AddItemToObject ( params , " callID " , cJSON_CreateString ( call_id ) ) ;
}
if ( paramsP ) {
* paramsP = params ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
return msg ;
}
static void jrpc_add_id ( cJSON * obj , cJSON * jid , const char * idstr , int id )
{
if ( jid ) {
cJSON_AddItemToObject ( obj , " id " , cJSON_Duplicate ( jid , 1 ) ) ;
} else if ( idstr ) {
cJSON_AddItemToObject ( obj , " id " , zstr ( idstr ) ? cJSON_CreateNull ( ) : cJSON_CreateString ( idstr ) ) ;
} else {
cJSON_AddItemToObject ( obj , " id " , cJSON_CreateNumber ( id ) ) ;
}
}
static void jrpc_add_error ( cJSON * obj , int code , const char * message , cJSON * jid )
{
cJSON * error = cJSON_CreateObject ( ) ;
cJSON_AddItemToObject ( obj , " error " , error ) ;
cJSON_AddItemToObject ( error , " code " , cJSON_CreateNumber ( code ) ) ;
cJSON_AddItemToObject ( error , " message " , cJSON_CreateString ( message ) ) ;
if ( ! cJSON_GetObjectItem ( obj , " id " ) ) {
jrpc_add_id ( obj , jid , " " , 0 ) ;
}
}
static void jrpc_add_result ( cJSON * obj , cJSON * result )
{
if ( result ) {
cJSON_AddItemToObject ( obj , " result " , result ) ;
}
}
static switch_ssize_t ws_write_json ( jsock_t * jsock , cJSON * * json , switch_bool_t destroy )
{
char * json_text ;
switch_ssize_t r = - 1 ;
switch_assert ( json ) ;
if ( ! * json ) {
2014-07-15 21:01:38 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ALERT , " WRITE NULL JS ERROR % " SWITCH_SIZE_T_FMT " \n " , r ) ;
2014-06-11 12:48:46 -05:00
return r ;
}
2014-06-11 17:11:47 -05:00
if ( ! zstr ( jsock - > uuid_str ) ) {
2014-06-11 12:48:46 -05:00
cJSON * result = cJSON_GetObjectItem ( * json , " result " ) ;
if ( result ) {
cJSON_AddItemToObject ( result , " sessid " , cJSON_CreateString ( jsock - > uuid_str ) ) ;
}
}
if ( ( json_text = cJSON_PrintUnformatted ( * json ) ) ) {
2017-02-09 17:23:30 -06:00
if ( jsock - > profile - > debug | | verto_globals . debug ) {
2021-05-12 04:09:54 +00:00
//char *log_text = cJSON_Prin(*json);
switch_log_printf ( SWITCH_CHANNEL_LOG , verto_globals . debug_level , " WRITE %s [%s] \n " , jsock - > name , json_text ) ;
//free(log_text);
2014-06-11 12:48:46 -05:00
}
switch_mutex_lock ( jsock - > write_mutex ) ;
2020-03-25 03:49:19 +04:00
r = kws_write_frame ( jsock - > ws , WSOC_TEXT , json_text , strlen ( json_text ) ) ;
2014-06-11 12:48:46 -05:00
switch_mutex_unlock ( jsock - > write_mutex ) ;
switch_safe_free ( json_text ) ;
}
if ( destroy ) {
cJSON_Delete ( * json ) ;
* json = NULL ;
}
2014-07-09 13:30:04 -05:00
if ( r < = 0 ) {
2014-07-15 21:01:38 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ALERT , " WRITE RETURNED ERROR % " SWITCH_SIZE_T_FMT " \n " , r ) ;
2014-07-16 00:37:09 +05:00
jsock - > drop = 1 ;
2014-07-24 02:44:34 -04:00
jsock - > ready = 0 ;
2014-07-09 13:30:04 -05:00
}
2014-06-11 12:48:46 -05:00
return r ;
}
2014-07-24 02:44:34 -04:00
static switch_status_t jsock_queue_event ( jsock_t * jsock , cJSON * * json , switch_bool_t destroy )
2014-07-18 01:03:57 +05:00
{
switch_status_t status = SWITCH_STATUS_FALSE ;
2014-07-24 02:44:34 -04:00
cJSON * jp ;
if ( destroy ) {
jp = * json ;
} else {
jp = cJSON_Duplicate ( * json , 1 ) ;
}
if ( switch_queue_trypush ( jsock - > event_queue , jp ) = = SWITCH_STATUS_SUCCESS ) {
2014-07-18 01:03:57 +05:00
status = SWITCH_STATUS_SUCCESS ;
2017-01-06 02:10:15 -05:00
2014-07-18 01:03:57 +05:00
if ( jsock - > lost_events ) {
int le = jsock - > lost_events ;
jsock - > lost_events = 0 ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Lost %d json events! \n " , le ) ;
}
} else {
if ( + + jsock - > lost_events > MAX_MISSED ) {
jsock - > drop + + ;
}
2014-07-24 02:44:34 -04:00
if ( ! destroy ) {
cJSON_Delete ( jp ) ;
jp = NULL ;
}
2014-07-18 01:03:57 +05:00
}
2014-07-24 02:44:34 -04:00
if ( destroy ) {
* json = NULL ;
}
2014-07-18 01:03:57 +05:00
return status ;
}
2021-03-14 19:21:01 +00:00
static switch_bool_t event_channel_check_auth ( jsock_t * jsock , const char * event_channel ) ;
2020-10-22 19:25:29 +00:00
static void write_event ( const char * event_channel , const char * super_channel , jsock_t * use_jsock , cJSON * event )
2014-06-11 12:48:46 -05:00
{
jsock_sub_node_head_t * head ;
2017-01-06 02:10:15 -05:00
if ( ( head = switch_core_hash_find ( verto_globals . event_channel_hash , event_channel ) ) ) {
2014-06-11 12:48:46 -05:00
jsock_sub_node_t * np ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
for ( np = head - > node ; np ; np = np - > next ) {
cJSON * msg = NULL , * params ;
2020-08-25 23:51:38 +00:00
2014-06-11 12:48:46 -05:00
if ( ! use_jsock | | use_jsock = = np - > jsock ) {
2020-08-25 23:51:38 +00:00
const char * visibility ;
//char *tmp;
2020-10-22 19:25:29 +00:00
2020-08-25 23:51:38 +00:00
if ( ( visibility = cJSON_GetObjectCstr ( event , " contentVisibility " ) ) ) {
2020-10-22 19:25:29 +00:00
if ( strcasecmp ( visibility , " public " ) & & ( np - > jsock - > id & & ! strncasecmp ( np - > jsock - > id , " guest " , 5 ) ) ) {
int perm = 0 ;
2021-03-14 19:21:01 +00:00
perm = event_channel_check_auth ( np - > jsock , event_channel ) ;
if ( ! perm & & super_channel ) {
perm = event_channel_check_auth ( np - > jsock , super_channel ) ;
}
2020-10-22 19:25:29 +00:00
2021-03-14 19:21:01 +00:00
if ( ! perm ) {
perm = switch_event_channel_permission_verify ( np - > jsock - > uuid_str , event_channel ) ;
}
2020-10-22 19:25:29 +00:00
if ( ! perm & & super_channel ) {
perm = switch_event_channel_permission_verify ( np - > jsock - > uuid_str , super_channel ) ;
}
2021-03-14 19:21:01 +00:00
2020-10-22 19:25:29 +00:00
if ( ! perm ) {
2020-08-27 01:41:40 +00:00
continue ;
}
2020-08-25 23:51:38 +00:00
}
}
//tmp = cJSON_Print(event);
//printf("%s\n", tmp);
//free(tmp);
2014-06-11 12:48:46 -05:00
params = cJSON_Duplicate ( event , 1 ) ;
2014-06-20 19:21:56 +05:00
cJSON_AddItemToObject ( params , " eventSerno " , cJSON_CreateNumber ( np - > serno + + ) ) ;
2020-06-03 21:50:29 +00:00
cJSON_AddItemToObject ( params , " subscribedChannel " , cJSON_CreateString ( head - > event_channel ) ) ;
2014-06-11 12:48:46 -05:00
msg = jrpc_new_req ( " verto.event " , NULL , & params ) ;
2020-06-03 21:50:29 +00:00
2014-07-24 02:44:34 -04:00
jsock_queue_event ( np - > jsock , & msg , SWITCH_TRUE ) ;
2014-06-11 12:48:46 -05:00
}
}
}
}
static void jsock_send_event ( cJSON * event )
{
2021-03-05 01:46:01 +00:00
const char * event_channel , * session_uuid = NULL , * direct_id = NULL ;
2014-06-11 12:48:46 -05:00
jsock_t * use_jsock = NULL ;
switch_core_session_t * session = NULL ;
if ( ! ( event_channel = cJSON_GetObjectCstr ( event , " eventChannel " ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " NO EVENT CHANNEL SPECIFIED \n " ) ;
return ;
}
2021-03-05 01:46:01 +00:00
if ( ! ( direct_id = cJSON_GetObjectCstr ( event , " eventChannelSessid " ) ) ) {
direct_id = event_channel ;
}
2014-06-11 12:48:46 -05:00
2021-03-05 01:46:01 +00:00
if ( ( session_uuid = cJSON_GetObjectCstr ( event , " sessid " ) ) ) {
if ( ! ( use_jsock = get_jsock ( session_uuid ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Socket %s not connected \n " , session_uuid ) ;
return ;
}
} else {
if ( ( session = switch_core_session_locate ( direct_id ) ) ) {
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
const char * jsock_uuid_str = switch_channel_get_variable ( channel , " jsock_uuid_str " ) ;
if ( jsock_uuid_str ) {
use_jsock = get_jsock ( jsock_uuid_str ) ;
}
switch_core_session_rwunlock ( session ) ;
2014-06-11 12:48:46 -05:00
}
}
2021-03-05 01:46:01 +00:00
if ( use_jsock | | ( use_jsock = get_jsock ( direct_id ) ) ) { /* implicit subscription to channel identical to the connection uuid or session uuid */
2014-06-11 12:48:46 -05:00
cJSON * msg = NULL , * params ;
params = cJSON_Duplicate ( event , 1 ) ;
msg = jrpc_new_req ( " verto.event " , NULL , & params ) ;
2014-07-24 02:44:34 -04:00
jsock_queue_event ( use_jsock , & msg , SWITCH_TRUE ) ;
2014-06-11 12:48:46 -05:00
switch_thread_rwlock_unlock ( use_jsock - > rwlock ) ;
use_jsock = NULL ;
return ;
}
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_rdlock ( verto_globals . event_channel_rwlock ) ;
2020-10-22 19:25:29 +00:00
write_event ( event_channel , NULL , use_jsock , event ) ;
2014-06-11 12:48:46 -05:00
if ( strchr ( event_channel , ' . ' ) ) {
char * main_channel = strdup ( event_channel ) ;
2019-07-12 19:59:40 +04:00
char * p ;
switch_assert ( main_channel ) ;
p = strchr ( main_channel , ' . ' ) ;
2014-06-11 12:48:46 -05:00
if ( p ) * p = ' \0 ' ;
2020-10-22 19:25:29 +00:00
write_event ( main_channel , event_channel , use_jsock , event ) ;
2014-06-11 12:48:46 -05:00
free ( main_channel ) ;
}
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_unlock ( verto_globals . event_channel_rwlock ) ;
2014-06-11 12:48:46 -05:00
}
static jrpc_func_t jrpc_get_func ( jsock_t * jsock , const char * method )
{
2017-01-06 02:10:15 -05:00
jrpc_func_t func = NULL ;
2014-06-11 12:48:46 -05:00
char * main_method = NULL ;
switch_assert ( method ) ;
if ( jsock - > allowed_methods ) {
if ( strchr ( method , ' . ' ) ) {
char * p ;
main_method = strdup ( method ) ;
2019-07-12 19:59:40 +04:00
switch_assert ( main_method ) ;
2014-06-11 12:48:46 -05:00
if ( ( p = strchr ( main_method , ' . ' ) ) ) {
* p = ' \0 ' ;
}
}
if ( ! ( switch_event_get_header ( jsock - > allowed_methods , method ) | | ( main_method & & switch_event_get_header ( jsock - > allowed_methods , main_method ) ) ) ) {
goto end ;
}
}
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . method_mutex ) ;
func = ( jrpc_func_t ) ( intptr_t ) switch_core_hash_find ( verto_globals . method_hash , method ) ;
switch_mutex_unlock ( verto_globals . method_mutex ) ;
2014-06-11 12:48:46 -05:00
end :
switch_safe_free ( main_method ) ;
return func ;
}
static void jrpc_add_func ( const char * method , jrpc_func_t func )
{
switch_assert ( method ) ;
switch_assert ( func ) ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . method_mutex ) ;
switch_core_hash_insert ( verto_globals . method_hash , method , ( void * ) ( intptr_t ) func ) ;
switch_mutex_unlock ( verto_globals . method_mutex ) ;
2014-06-11 12:48:46 -05:00
}
static char * MARKER = " X " ;
2020-05-08 01:20:14 +00:00
static void set_perm ( const char * str , switch_event_t * * event , switch_bool_t add )
2014-06-11 12:48:46 -05:00
{
char delim = ' , ' ;
char * cur , * next ;
char * edup ;
if ( ! zstr ( str ) ) {
if ( ! strcasecmp ( str , " __ANY__ " ) ) {
return ;
}
}
2020-05-08 01:20:14 +00:00
if ( event & & ! * event ) {
switch_event_create ( event , SWITCH_EVENT_REQUEST_PARAMS ) ;
}
2023-06-12 17:25:37 +03:00
if ( ! zstr ( str ) & & event & & * event ) {
2014-06-11 12:48:46 -05:00
edup = strdup ( str ) ;
2019-07-12 19:59:40 +04:00
switch_assert ( edup ) ;
2014-06-11 12:48:46 -05:00
if ( strchr ( edup , ' ' ) ) {
delim = ' ' ;
}
2023-07-04 10:12:44 +01:00
for ( cur = edup ; cur ; ) {
2014-06-11 12:48:46 -05:00
if ( ( next = strchr ( cur , delim ) ) ) {
* next + + = ' \0 ' ;
}
2020-05-08 01:20:14 +00:00
if ( add ) {
switch_event_add_header_string ( * event , SWITCH_STACK_BOTTOM , cur , MARKER ) ;
} else {
switch_event_del_header ( * event , cur ) ;
}
2014-06-11 12:48:46 -05:00
cur = next ;
}
2017-01-06 02:10:15 -05:00
switch_safe_free ( edup ) ;
2014-06-11 12:48:46 -05:00
}
}
static void check_permissions ( jsock_t * jsock , switch_xml_t x_user , cJSON * params )
{
switch_xml_t x_param , x_params ;
const char * allowed_methods = NULL , * allowed_jsapi = NULL , * allowed_fsapi = NULL , * allowed_event_channels = NULL ;
if ( ( x_params = switch_xml_child ( x_user , " params " ) ) ) {
for ( x_param = switch_xml_child ( x_params , " param " ) ; x_param ; x_param = x_param - > next ) {
const char * var = switch_xml_attr ( x_param , " name " ) ;
const char * val = switch_xml_attr ( x_param , " value " ) ;
if ( zstr ( val ) | | zstr ( var ) ) {
continue ;
}
if ( ! strcasecmp ( var , " jsonrpc-allowed-methods " ) ) {
allowed_methods = val ;
}
if ( ! strcasecmp ( var , " jsonrpc-allowed-jsapi " ) ) {
allowed_jsapi = val ;
}
if ( ! strcasecmp ( var , " jsonrpc-allowed-fsapi " ) ) {
allowed_fsapi = val ;
}
if ( ! strcasecmp ( var , " jsonrpc-allowed-event-channels " ) ) {
allowed_event_channels = val ;
}
}
}
2014-07-18 01:03:57 +05:00
2020-05-08 01:20:14 +00:00
set_perm ( allowed_methods , & jsock - > allowed_methods , SWITCH_TRUE ) ;
set_perm ( allowed_jsapi , & jsock - > allowed_jsapi , SWITCH_TRUE ) ;
set_perm ( allowed_fsapi , & jsock - > allowed_fsapi , SWITCH_TRUE ) ;
set_perm ( allowed_event_channels , & jsock - > allowed_event_channels , SWITCH_TRUE ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_event_add_header_string ( jsock - > allowed_methods , SWITCH_STACK_BOTTOM , " login " , MARKER ) ;
}
2020-05-08 01:20:14 +00:00
static switch_status_t add_perm ( const char * sessid , const char * type , const char * value , switch_bool_t add )
{
jsock_t * jsock = NULL ;
switch_status_t status = SWITCH_STATUS_FALSE ;
if ( type & & value & & ( jsock = get_jsock ( sessid ) ) ) {
status = SWITCH_STATUS_SUCCESS ;
if ( ! strcmp ( type , " methods " ) ) {
set_perm ( value , & jsock - > allowed_methods , add ) ;
} else if ( ! strcmp ( type , " jsapi " ) ) {
set_perm ( value , & jsock - > allowed_jsapi , add ) ;
} else if ( ! strcmp ( type , " fsapi " ) ) {
set_perm ( value , & jsock - > allowed_fsapi , add ) ;
} else if ( ! strcmp ( type , " event_channels " ) ) {
set_perm ( value , & jsock - > allowed_event_channels , add ) ;
} else {
status = SWITCH_STATUS_FALSE ;
}
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
}
return status ;
}
2014-08-01 23:07:13 +05:00
static void login_fire_custom_event ( jsock_t * jsock , cJSON * params , int success , const char * result_txt )
{
switch_event_t * s_event ;
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_LOGIN ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " verto_profile_name " , jsock - > profile - > name ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " verto_client_address " , jsock - > name ) ;
2017-05-09 12:22:15 -05:00
if ( params ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " verto_login " , cJSON_GetObjectCstr ( params , " login " ) ) ;
if ( success ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " verto_sessid " , cJSON_GetObjectCstr ( params , " sessid " ) ) ;
}
2014-08-01 23:07:13 +05:00
}
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " verto_success " , " %d " , success ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " verto_result_txt " , result_txt ) ;
switch_event_fire ( & s_event ) ;
}
}
2014-06-11 12:48:46 -05:00
static switch_bool_t check_auth ( jsock_t * jsock , cJSON * params , int * code , char * message , switch_size_t mlen )
{
switch_bool_t r = SWITCH_FALSE ;
const char * passwd = NULL ;
const char * login = NULL ;
2015-04-25 10:57:09 -05:00
cJSON * json_ptr = NULL ;
2016-12-25 16:30:54 -06:00
char * input = NULL ;
char * a1_hash = NULL ;
char a1_hash_buff [ 33 ] = " " ;
2014-06-11 12:48:46 -05:00
if ( ! params ) {
* code = CODE_AUTH_FAILED ;
switch_snprintf ( message , mlen , " Missing params " ) ;
goto end ;
}
2017-01-06 02:10:15 -05:00
login = cJSON_GetObjectCstr ( params , " login " ) ;
passwd = cJSON_GetObjectCstr ( params , " passwd " ) ;
2014-06-11 12:48:46 -05:00
if ( zstr ( login ) ) {
goto end ;
}
if ( zstr ( passwd ) ) {
* code = CODE_AUTH_FAILED ;
switch_snprintf ( message , mlen , " Missing passwd " ) ;
2014-08-01 23:07:13 +05:00
login_fire_custom_event ( jsock , params , 0 , " Missing passwd " ) ;
2014-06-11 12:48:46 -05:00
goto end ;
}
2019-01-30 09:40:51 -05:00
if ( ! strcmp ( login , " root " ) & & jsock - > profile - > root_passwd ) {
2014-06-11 12:48:46 -05:00
if ( ! ( r = ! strcmp ( passwd , jsock - > profile - > root_passwd ) ) ) {
* code = CODE_AUTH_FAILED ;
switch_snprintf ( message , mlen , " Authentication Failure " ) ;
2014-08-01 23:07:13 +05:00
login_fire_custom_event ( jsock , params , 0 , " Authentication Failure " ) ;
2014-06-11 12:48:46 -05:00
}
} else if ( ! zstr ( jsock - > profile - > userauth ) ) {
switch_xml_t x_user = NULL ;
char * id = NULL , * domain = NULL ;
switch_event_t * req_params ;
if ( * jsock - > profile - > userauth = = ' @ ' ) {
domain = jsock - > profile - > userauth + 1 ;
id = ( char * ) login ;
} else if ( switch_true ( jsock - > profile - > userauth ) ) {
id = switch_core_strdup ( jsock - > pool , login ) ;
2020-08-13 21:08:32 +00:00
if ( jsock - > profile - > chop_domain & & ( domain = strchr ( id , ' @ ' ) ) ) {
2014-06-11 12:48:46 -05:00
* domain + + = ' \0 ' ;
}
2020-08-13 21:08:32 +00:00
2014-06-11 12:48:46 -05:00
}
2015-04-23 10:45:48 -05:00
if ( jsock - > profile - > register_domain ) {
domain = jsock - > profile - > register_domain ;
}
2014-06-11 12:48:46 -05:00
if ( ! ( id & & domain ) ) {
* code = CODE_AUTH_FAILED ;
switch_snprintf ( message , mlen , " Missing or improper credentials " ) ;
goto end ;
}
switch_event_create ( & req_params , SWITCH_EVENT_REQUEST_PARAMS ) ;
switch_assert ( req_params ) ;
2015-04-25 10:57:09 -05:00
if ( ( json_ptr = cJSON_GetObjectItem ( params , " loginParams " ) ) ) {
2015-02-21 12:11:24 -06:00
cJSON * i ;
2017-01-06 02:10:15 -05:00
2015-04-25 10:57:09 -05:00
for ( i = json_ptr - > child ; i ; i = i - > next ) {
2015-02-21 12:11:24 -06:00
if ( i - > type = = cJSON_True ) {
switch_event_add_header_string ( req_params , SWITCH_STACK_BOTTOM , i - > string , " true " ) ;
} else if ( i - > type = = cJSON_False ) {
switch_event_add_header_string ( req_params , SWITCH_STACK_BOTTOM , i - > string , " false " ) ;
} else if ( ! zstr ( i - > string ) & & ! zstr ( i - > valuestring ) ) {
switch_event_add_header_string ( req_params , SWITCH_STACK_BOTTOM , i - > string , i - > valuestring ) ;
}
}
}
2015-04-25 10:57:09 -05:00
if ( ( json_ptr = cJSON_GetObjectItem ( params , " userVariables " ) ) ) {
cJSON * i ;
2021-01-24 19:08:44 +00:00
switch_mutex_lock ( jsock - > flag_mutex ) ;
2015-04-25 10:57:09 -05:00
for ( i = json_ptr - > child ; i ; i = i - > next ) {
if ( i - > type = = cJSON_True ) {
switch_event_add_header_string ( jsock - > user_vars , SWITCH_STACK_BOTTOM , i - > string , " true " ) ;
} else if ( i - > type = = cJSON_False ) {
switch_event_add_header_string ( jsock - > user_vars , SWITCH_STACK_BOTTOM , i - > string , " false " ) ;
} else if ( ! zstr ( i - > string ) & & ! zstr ( i - > valuestring ) ) {
switch_event_add_header_string ( jsock - > user_vars , SWITCH_STACK_BOTTOM , i - > string , i - > valuestring ) ;
}
}
2021-01-24 19:08:44 +00:00
switch_mutex_unlock ( jsock - > flag_mutex ) ;
2015-04-25 10:57:09 -05:00
}
2020-04-05 20:15:12 +00:00
if ( jsock - > profile - > send_passwd | | verto_globals . send_passwd ) {
switch_event_add_header_string ( req_params , SWITCH_STACK_BOTTOM , " user_supplied_pass " , passwd ) ;
}
2014-06-11 12:48:46 -05:00
switch_event_add_header_string ( req_params , SWITCH_STACK_BOTTOM , " action " , " jsonrpc-authenticate " ) ;
2017-01-06 02:10:15 -05:00
2014-07-24 10:13:32 +05:00
if ( switch_xml_locate_user_merged ( " id " , id , domain , NULL , & x_user , req_params ) ! = SWITCH_STATUS_SUCCESS & & ! jsock - > profile - > blind_reg ) {
2014-06-11 12:48:46 -05:00
* code = CODE_AUTH_FAILED ;
switch_snprintf ( message , mlen , " Login Incorrect " ) ;
2014-08-01 23:07:13 +05:00
login_fire_custom_event ( jsock , params , 0 , " Login Incorrect " ) ;
2023-06-12 17:25:37 +03:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Login incorrect for user: %s domain: %s \n " , id , domain ) ;
2014-06-11 12:48:46 -05:00
} else {
switch_xml_t x_param , x_params ;
const char * use_passwd = NULL , * verto_context = NULL , * verto_dialplan = NULL ;
2021-02-03 21:18:07 +00:00
time_t now = switch_epoch_time_now ( NULL ) ;
2014-06-11 12:48:46 -05:00
2023-03-29 19:14:54 +03:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Login sucessful for user: %s domain: %s \n " , id , domain ) ;
2021-04-02 23:02:38 +00:00
2021-02-03 21:18:07 +00:00
jsock - > logintime = now ;
2014-06-11 12:48:46 -05:00
jsock - > id = switch_core_strdup ( jsock - > pool , id ) ;
jsock - > domain = switch_core_strdup ( jsock - > pool , domain ) ;
jsock - > uid = switch_core_sprintf ( jsock - > pool , " %s@%s " , id , domain ) ;
2014-07-24 02:44:34 -04:00
jsock - > ready = 1 ;
2017-01-06 02:10:15 -05:00
2014-07-24 10:13:32 +05:00
if ( ! x_user ) {
switch_event_destroy ( & req_params ) ;
r = SWITCH_TRUE ;
goto end ;
}
2014-06-11 12:48:46 -05:00
if ( ( x_params = switch_xml_child ( x_user , " params " ) ) ) {
for ( x_param = switch_xml_child ( x_params , " param " ) ; x_param ; x_param = x_param - > next ) {
const char * var = switch_xml_attr_soft ( x_param , " name " ) ;
const char * val = switch_xml_attr_soft ( x_param , " value " ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! use_passwd & & ! strcasecmp ( var , " password " ) ) {
use_passwd = val ;
} else if ( ! strcasecmp ( var , " jsonrpc-password " ) ) {
use_passwd = val ;
2016-12-25 16:30:54 -06:00
} else if ( ! strcasecmp ( var , " a1-hash " ) ) {
use_passwd = val ;
input = switch_mprintf ( " %s:%s:%s " , id , domain , passwd ) ;
switch_md5_string ( a1_hash_buff , ( void * ) input , strlen ( input ) ) ;
a1_hash = a1_hash_buff ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " a1-hash-plain = '%s' a1-hash-md5 = '%s' \n " , input , a1_hash ) ;
switch_safe_free ( input ) ;
2014-06-11 12:48:46 -05:00
} else if ( ! strcasecmp ( var , " verto-context " ) ) {
verto_context = val ;
} else if ( ! strcasecmp ( var , " verto-dialplan " ) ) {
verto_dialplan = val ;
}
2014-06-13 23:15:36 +05:00
switch_event_add_header_string ( jsock - > params , SWITCH_STACK_BOTTOM , var , val ) ;
2014-06-11 12:48:46 -05:00
}
}
if ( ( x_params = switch_xml_child ( x_user , " variables " ) ) ) {
for ( x_param = switch_xml_child ( x_params , " variable " ) ; x_param ; x_param = x_param - > next ) {
const char * var = switch_xml_attr_soft ( x_param , " name " ) ;
const char * val = switch_xml_attr_soft ( x_param , " value " ) ;
2017-01-06 02:10:15 -05:00
2020-04-13 23:17:37 +00:00
switch_mutex_lock ( jsock - > flag_mutex ) ;
2014-06-13 23:15:36 +05:00
switch_event_add_header_string ( jsock - > vars , SWITCH_STACK_BOTTOM , var , val ) ;
2021-01-24 19:08:44 +00:00
switch_event_add_header_string ( jsock - > user_vars , SWITCH_STACK_BOTTOM , var , val ) ;
2020-04-13 23:17:37 +00:00
switch_mutex_unlock ( jsock - > flag_mutex ) ;
2021-02-03 21:18:07 +00:00
2021-03-31 20:13:38 +00:00
switch_clear_flag ( jsock , JPFLAG_AUTH_EXPIRED ) ;
2021-02-03 21:18:07 +00:00
if ( ! strcmp ( var , " login-expires " ) ) {
uint32_t tmp = atol ( val ) ;
if ( tmp > now ) {
jsock - > exptime = tmp ;
2021-04-02 23:02:38 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Login expire time for %s set to %ld seconds [%ld] [%ld] \n " , jsock - > uid , tmp - now , jsock - > exptime , now ) ;
2021-02-03 21:18:07 +00:00
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Invalid expire time for %s. Defaulting to 300 sec \n " , jsock - > uid ) ;
jsock - > exptime = now + 300 ;
}
}
2014-06-11 12:48:46 -05:00
}
}
if ( ! zstr ( verto_dialplan ) ) {
jsock - > dialplan = switch_core_strdup ( jsock - > pool , verto_dialplan ) ;
}
if ( ! zstr ( verto_context ) ) {
jsock - > context = switch_core_strdup ( jsock - > pool , verto_context ) ;
}
2016-12-25 16:30:54 -06:00
2021-10-19 03:03:55 +03:00
if ( ! use_passwd | | zstr ( use_passwd ) | | strcmp ( a1_hash ? a1_hash : passwd , use_passwd ) ) {
2014-06-11 12:48:46 -05:00
r = SWITCH_FALSE ;
* code = CODE_AUTH_FAILED ;
switch_snprintf ( message , mlen , " Authentication Failure " ) ;
2014-07-31 22:59:21 +05:00
jsock - > uid = NULL ;
2014-08-01 23:07:13 +05:00
login_fire_custom_event ( jsock , params , 0 , " Authentication Failure " ) ;
2020-11-09 03:49:30 +00:00
switch_xml_clear_user_cache ( " id " , id , domain ) ;
2014-06-11 12:48:46 -05:00
} else {
2016-12-25 16:30:54 -06:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " auth using %s \n " , a1_hash ? " a1-hash " : " username & password " ) ;
2014-06-11 12:48:46 -05:00
r = SWITCH_TRUE ;
check_permissions ( jsock , x_user , params ) ;
}
2016-12-25 16:30:54 -06:00
2014-06-11 12:48:46 -05:00
switch_xml_free ( x_user ) ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_event_destroy ( & req_params ) ;
}
end :
return r ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
}
static void set_call_params ( cJSON * params , verto_pvt_t * tech_pvt ) {
const char * caller_id_name = NULL ;
const char * caller_id_number = NULL ;
2014-08-19 03:25:24 +05:00
const char * callee_id_name = NULL ;
const char * callee_id_number = NULL ;
2017-02-22 12:52:32 +03:00
const char * prefix = " verto_h_ " ;
switch_event_header_t * var = NULL ;
2014-08-04 23:08:29 +05:00
2014-08-19 03:25:24 +05:00
caller_id_name = switch_channel_get_variable ( tech_pvt - > channel , " caller_id_name " ) ;
2017-01-06 02:10:15 -05:00
caller_id_number = switch_channel_get_variable ( tech_pvt - > channel , " caller_id_number " ) ;
2014-08-19 03:25:24 +05:00
callee_id_name = switch_channel_get_variable ( tech_pvt - > channel , " callee_id_name " ) ;
callee_id_number = switch_channel_get_variable ( tech_pvt - > channel , " callee_id_number " ) ;
2014-08-04 23:08:29 +05:00
2014-08-19 03:25:24 +05:00
if ( caller_id_name ) cJSON_AddItemToObject ( params , " caller_id_name " , cJSON_CreateString ( caller_id_name ) ) ;
if ( caller_id_number ) cJSON_AddItemToObject ( params , " caller_id_number " , cJSON_CreateString ( caller_id_number ) ) ;
if ( callee_id_name ) cJSON_AddItemToObject ( params , " callee_id_name " , cJSON_CreateString ( callee_id_name ) ) ;
if ( callee_id_number ) cJSON_AddItemToObject ( params , " callee_id_number " , cJSON_CreateString ( callee_id_number ) ) ;
2017-01-06 02:10:15 -05:00
cJSON_AddItemToObject ( params , " display_direction " ,
2014-08-19 03:25:24 +05:00
cJSON_CreateString ( switch_channel_direction ( tech_pvt - > channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ? " outbound " : " inbound " ) ) ;
2014-07-18 22:05:07 +05:00
2017-02-22 12:52:32 +03:00
for ( var = switch_channel_variable_first ( tech_pvt - > channel ) ; var ; var = var - > next ) {
const char * name = ( char * ) var - > name ;
char * value = ( char * ) var - > value ;
if ( ! strncasecmp ( name , prefix , strlen ( prefix ) ) ) {
cJSON_AddItemToObject ( params , name , cJSON_CreateString ( value ) ) ;
}
}
switch_channel_variable_last ( tech_pvt - > channel ) ;
2014-06-11 12:48:46 -05:00
}
static jsock_t * get_jsock ( const char * uuid )
{
jsock_t * jsock = NULL ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . jsock_mutex ) ;
if ( ( jsock = switch_core_hash_find ( verto_globals . jsock_hash , uuid ) ) ) {
2014-06-11 12:48:46 -05:00
if ( switch_thread_rwlock_tryrdlock ( jsock - > rwlock ) ! = SWITCH_STATUS_SUCCESS ) {
jsock = NULL ;
}
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . jsock_mutex ) ;
2014-06-11 12:48:46 -05:00
return jsock ;
}
2020-04-13 23:17:37 +00:00
static void tech_reattach ( verto_pvt_t * tech_pvt , jsock_t * jsock ) ;
2014-06-11 12:48:46 -05:00
static void attach_jsock ( jsock_t * jsock )
{
2015-01-05 21:14:35 -06:00
jsock_t * jp ;
int proceed = 1 ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . jsock_mutex ) ;
2015-01-05 21:14:35 -06:00
2015-08-31 17:08:52 -04:00
switch_assert ( jsock ) ;
2017-02-09 17:23:30 -06:00
if ( ( jp = switch_core_hash_find ( verto_globals . jsock_hash , jsock - > uuid_str ) ) ) {
2015-01-05 21:14:35 -06:00
if ( jp = = jsock ) {
proceed = 0 ;
} else {
cJSON * params = NULL ;
cJSON * msg = NULL ;
msg = jrpc_new_req ( " verto.punt " , NULL , & params ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " New connection for session %s dropping previous connection. \n " , jsock - > uuid_str ) ;
2017-02-09 17:23:30 -06:00
switch_core_hash_delete ( verto_globals . jsock_hash , jsock - > uuid_str ) ;
2015-01-05 21:14:35 -06:00
ws_write_json ( jp , & msg , SWITCH_TRUE ) ;
2020-04-13 23:17:37 +00:00
detach_calls ( jp ) ;
2015-01-05 21:14:35 -06:00
cJSON_Delete ( msg ) ;
2016-02-18 11:44:16 -06:00
jp - > nodelete = 1 ;
2015-01-05 21:14:35 -06:00
jp - > drop = 1 ;
2020-04-13 23:17:37 +00:00
jsock - > attach_timer = 5 ;
2015-01-05 21:14:35 -06:00
}
}
if ( proceed ) {
2017-02-09 17:23:30 -06:00
switch_core_hash_insert ( verto_globals . jsock_hash , jsock - > uuid_str , jsock ) ;
2015-01-05 21:14:35 -06:00
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . jsock_mutex ) ;
2014-06-11 12:48:46 -05:00
}
static void detach_jsock ( jsock_t * jsock )
{
2016-02-18 11:44:16 -06:00
if ( jsock - > nodelete ) {
return ;
}
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . jsock_mutex ) ;
switch_core_hash_delete ( verto_globals . jsock_hash , jsock - > uuid_str ) ;
switch_mutex_unlock ( verto_globals . jsock_mutex ) ;
2014-06-11 12:48:46 -05:00
}
static int attach_wake ( void )
{
switch_status_t status ;
int tries = 0 ;
top :
2017-01-06 02:10:15 -05:00
2017-02-09 17:23:30 -06:00
status = switch_mutex_trylock ( verto_globals . detach_mutex ) ;
2014-06-11 12:48:46 -05:00
if ( status = = SWITCH_STATUS_SUCCESS ) {
2017-02-09 17:23:30 -06:00
switch_thread_cond_signal ( verto_globals . detach_cond ) ;
switch_mutex_unlock ( verto_globals . detach_mutex ) ;
2014-06-11 12:48:46 -05:00
return 1 ;
} else {
2017-02-09 17:23:30 -06:00
if ( switch_mutex_trylock ( verto_globals . detach2_mutex ) = = SWITCH_STATUS_SUCCESS ) {
switch_mutex_unlock ( verto_globals . detach2_mutex ) ;
2014-06-11 12:48:46 -05:00
} else {
if ( + + tries < 10 ) {
switch_cond_next ( ) ;
goto top ;
}
}
}
return 0 ;
}
2020-04-25 01:35:59 +00:00
static void add_variables ( verto_pvt_t * tech_pvt , cJSON * params )
{
cJSON * jvariables = NULL ;
switch_event_header_t * hi ;
switch_event_t * variables ;
jvariables = cJSON_CreateObject ( ) ;
switch_channel_get_variables_prefix ( tech_pvt - > channel , " verto_svar_ " , & variables ) ;
for ( hi = variables - > headers ; hi ; hi = hi - > next ) {
cJSON_AddItemToObject ( jvariables , hi - > name , cJSON_CreateString ( hi - > value ) ) ;
}
cJSON_AddItemToObject ( params , " variables " , jvariables ) ;
switch_event_destroy ( & variables ) ;
}
2014-06-11 12:48:46 -05:00
static void tech_reattach ( verto_pvt_t * tech_pvt , jsock_t * jsock )
{
cJSON * params = NULL ;
cJSON * msg = NULL ;
tech_pvt - > detach_time = 0 ;
2017-02-09 17:23:30 -06:00
verto_globals . detached - - ;
2014-06-11 12:48:46 -05:00
attach_wake ( ) ;
switch_set_flag ( tech_pvt , TFLAG_ATTACH_REQ ) ;
msg = jrpc_new_req ( " verto.attach " , tech_pvt - > call_id , & params ) ;
2014-08-04 23:08:29 +05:00
2020-04-25 01:35:59 +00:00
add_variables ( tech_pvt , params ) ;
2019-03-04 18:39:20 +00:00
switch_channel_set_flag ( tech_pvt - > channel , CF_REATTACHED ) ;
2015-03-23 19:56:19 -05:00
switch_channel_set_flag ( tech_pvt - > channel , CF_REINVITE ) ;
switch_channel_set_flag ( tech_pvt - > channel , CF_RECOVERING ) ;
2023-10-18 20:24:14 +03:00
switch_core_media_gen_local_sdp ( tech_pvt - > session , SDP_OFFER , NULL , 0 , NULL , 0 ) ;
2015-03-23 19:56:19 -05:00
switch_channel_clear_flag ( tech_pvt - > channel , CF_REINVITE ) ;
switch_channel_clear_flag ( tech_pvt - > channel , CF_RECOVERING ) ;
switch_core_session_request_video_refresh ( tech_pvt - > session ) ;
2014-06-11 12:48:46 -05:00
cJSON_AddItemToObject ( params , " sdp " , cJSON_CreateString ( tech_pvt - > mparams - > local_sdp_str ) ) ;
2017-01-06 02:10:15 -05:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( tech_pvt - > session ) , SWITCH_LOG_DEBUG , " Local attach SDP %s: \n %s \n " ,
2014-06-13 03:02:09 -04:00
switch_channel_get_name ( tech_pvt - > channel ) ,
tech_pvt - > mparams - > local_sdp_str ) ;
2014-06-11 12:48:46 -05:00
set_call_params ( params , tech_pvt ) ;
2020-04-10 21:36:37 +00:00
switch_core_media_gen_key_frame ( tech_pvt - > session ) ;
switch_channel_set_flag ( tech_pvt - > channel , CF_VIDEO_REFRESH_REQ ) ;
2014-07-26 02:24:10 +05:00
jsock_queue_event ( jsock , & msg , SWITCH_TRUE ) ;
2014-06-11 12:48:46 -05:00
}
static void drop_detached ( void )
{
verto_pvt_t * tech_pvt ;
switch_time_t now = switch_epoch_time_now ( NULL ) ;
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_rdlock ( verto_globals . tech_rwlock ) ;
for ( tech_pvt = verto_globals . tech_head ; tech_pvt ; tech_pvt = tech_pvt - > next ) {
2014-06-11 12:48:46 -05:00
if ( ! switch_channel_up_nosig ( tech_pvt - > channel ) ) {
continue ;
}
2017-01-06 02:10:15 -05:00
2017-02-09 17:23:30 -06:00
if ( tech_pvt - > detach_time & & ( now - tech_pvt - > detach_time ) > verto_globals . detach_timeout ) {
2021-03-31 20:13:38 +00:00
jsock_t * jsock = NULL ;
if ( ( jsock = get_jsock ( tech_pvt - > jsock_uuid ) ) ) {
if ( switch_test_flag ( jsock , JPFLAG_AUTH_EXPIRED ) ) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH ) ;
}
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
} else {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE ) ;
}
2014-06-11 12:48:46 -05:00
}
}
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_unlock ( verto_globals . tech_rwlock ) ;
2014-06-11 12:48:46 -05:00
}
static void attach_calls ( jsock_t * jsock )
{
verto_pvt_t * tech_pvt ;
2017-07-06 13:54:08 -07:00
cJSON * msg = NULL ;
cJSON * params = NULL ;
cJSON * reattached_sessions = NULL ;
reattached_sessions = cJSON_CreateArray ( ) ;
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_rdlock ( verto_globals . tech_rwlock ) ;
for ( tech_pvt = verto_globals . tech_head ; tech_pvt ; tech_pvt = tech_pvt - > next ) {
2014-06-11 12:48:46 -05:00
if ( tech_pvt - > detach_time & & ! strcmp ( tech_pvt - > jsock_uuid , jsock - > uuid_str ) ) {
if ( ! switch_channel_up_nosig ( tech_pvt - > channel ) ) {
continue ;
}
tech_reattach ( tech_pvt , jsock ) ;
2021-05-10 23:56:36 +01:00
cJSON_AddItemToArray ( reattached_sessions , cJSON_CreateString ( switch_core_session_get_uuid ( tech_pvt - > session ) ) ) ;
2014-06-11 12:48:46 -05:00
}
}
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_unlock ( verto_globals . tech_rwlock ) ;
2017-07-06 13:54:08 -07:00
msg = jrpc_new_req ( " verto.clientReady " , NULL , & params ) ;
cJSON_AddItemToObject ( params , " reattached_sessions " , reattached_sessions ) ;
jsock_queue_event ( jsock , & msg , SWITCH_TRUE ) ;
2014-06-11 12:48:46 -05:00
}
static void detach_calls ( jsock_t * jsock )
{
verto_pvt_t * tech_pvt ;
2017-02-09 17:39:35 -06:00
int wake = 0 ;
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_rdlock ( verto_globals . tech_rwlock ) ;
for ( tech_pvt = verto_globals . tech_head ; tech_pvt ; tech_pvt = tech_pvt - > next ) {
2014-06-11 12:48:46 -05:00
if ( ! strcmp ( tech_pvt - > jsock_uuid , jsock - > uuid_str ) ) {
if ( ! switch_channel_up_nosig ( tech_pvt - > channel ) ) {
continue ;
}
2014-07-29 22:16:56 +05:00
if ( ! switch_channel_test_flag ( tech_pvt - > channel , CF_ANSWERED ) ) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
continue ;
}
2015-11-18 15:26:26 -06:00
2020-04-14 19:52:38 +00:00
if ( switch_channel_test_flag ( tech_pvt - > channel , CF_NO_RECOVER ) ) {
2015-11-18 15:26:26 -06:00
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
continue ;
}
2015-01-24 02:47:17 -06:00
switch_core_session_stop_media ( tech_pvt - > session ) ;
2014-06-11 12:48:46 -05:00
tech_pvt - > detach_time = switch_epoch_time_now ( NULL ) ;
2017-02-09 17:23:30 -06:00
verto_globals . detached + + ;
2017-02-09 17:39:35 -06:00
wake = 1 ;
2014-06-11 12:48:46 -05:00
}
}
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_unlock ( verto_globals . tech_rwlock ) ;
2017-02-09 17:39:35 -06:00
if ( wake ) attach_wake ( ) ;
2014-06-11 12:48:46 -05:00
}
static void process_jrpc_response ( jsock_t * jsock , cJSON * json )
{
}
static void set_session_id ( jsock_t * jsock , const char * uuid )
{
//cJSON *params, *msg = jrpc_new(0);
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! zstr ( uuid ) ) {
switch_set_string ( jsock - > uuid_str , uuid ) ;
2016-09-20 14:03:35 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s re-connecting session %s \n " , jsock - > name , jsock - > uuid_str ) ;
2014-06-11 12:48:46 -05:00
} else {
switch_uuid_str ( jsock - > uuid_str , sizeof ( jsock - > uuid_str ) ) ;
2016-09-20 14:03:35 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s new RPC session %s \n " , jsock - > name , jsock - > uuid_str ) ;
2014-06-11 12:48:46 -05:00
}
attach_jsock ( jsock ) ;
}
static cJSON * process_jrpc ( jsock_t * jsock , cJSON * json )
{
cJSON * reply = NULL , * echo = NULL , * id = NULL , * params = NULL , * response = NULL , * result ;
const char * method = NULL , * version = NULL , * sessid = NULL ;
jrpc_func_t func = NULL ;
switch_assert ( json ) ;
method = cJSON_GetObjectCstr ( json , " method " ) ;
result = cJSON_GetObjectItem ( json , " result " ) ;
version = cJSON_GetObjectCstr ( json , " jsonrpc " ) ;
id = cJSON_GetObjectItem ( json , " id " ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ( params = cJSON_GetObjectItem ( json , " params " ) ) ) {
sessid = cJSON_GetObjectCstr ( params , " sessid " ) ;
}
if ( ! switch_test_flag ( jsock , JPFLAG_INIT ) ) {
set_session_id ( jsock , sessid ) ;
switch_set_flag ( jsock , JPFLAG_INIT ) ;
}
if ( zstr ( version ) | | strcmp ( version , " 2.0 " ) ) {
reply = jrpc_new ( 0 ) ;
jrpc_add_error ( reply , CODE_INVALID , " Invalid message " , id ) ;
goto end ;
}
if ( result ) {
process_jrpc_response ( jsock , json ) ;
return NULL ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
reply = jrpc_new ( 0 ) ;
jrpc_add_id ( reply , id , " " , 0 ) ;
2021-02-09 19:34:37 +00:00
if ( ( ! switch_test_flag ( jsock , JPFLAG_AUTHED ) | | ( method & & ! strcmp ( method , " login " ) ) ) & & ( jsock - > profile - > userauth | | jsock - > profile - > root_passwd ) ) {
2014-06-11 12:48:46 -05:00
int code = CODE_AUTH_REQUIRED ;
char message [ 128 ] = " Authentication Required " ;
if ( ! check_auth ( jsock , params , & code , message , sizeof ( message ) ) ) {
jrpc_add_error ( reply , code , message , id ) ;
goto end ;
}
switch_set_flag ( jsock , JPFLAG_AUTHED ) ;
}
if ( ! method | | ! ( func = jrpc_get_func ( jsock , method ) ) ) {
jrpc_add_error ( reply , - 32601 , " Invalid Method, Missing Method or Permission Denied " , id ) ;
} else {
if ( func ( method , params , jsock , & response ) = = SWITCH_TRUE ) {
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( params ) {
echo = cJSON_GetObjectItem ( params , " echoParams " ) ;
}
if ( echo ) {
if ( ( echo - > type = = cJSON_True | | ( echo - > type = = cJSON_String & & switch_true ( echo - > valuestring ) ) ) ) {
cJSON_AddItemToObject ( response , " requestParams " , cJSON_Duplicate ( params , 1 ) ) ;
} else {
cJSON_AddItemToObject ( response , " requestParams " , cJSON_Duplicate ( echo , 1 ) ) ;
}
}
jrpc_add_result ( reply , response ) ;
} else {
if ( response ) {
cJSON_AddItemToObject ( reply , " error " , response ) ;
} else {
jrpc_add_error ( reply , - 32602 , " Permission Denied " , id ) ;
}
}
}
end :
return reply ;
}
static switch_status_t process_input ( jsock_t * jsock , uint8_t * data , switch_ssize_t bytes )
{
cJSON * json = NULL , * reply = NULL ;
char * ascii = ( char * ) data ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
if ( ascii ) {
json = cJSON_Parse ( ascii ) ;
}
if ( json ) {
2014-06-20 19:21:56 +05:00
2017-02-09 17:23:30 -06:00
if ( jsock - > profile - > debug | | verto_globals . debug ) {
2021-05-12 04:09:54 +00:00
char * log_text = cJSON_PrintUnformatted ( json ) ;
2020-04-01 00:31:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , verto_globals . debug_level , " READ %s [%s] \n " , jsock - > name , log_text ) ;
2014-06-20 19:21:56 +05:00
free ( log_text ) ;
}
2014-06-11 12:48:46 -05:00
if ( json - > type = = cJSON_Array ) { /* batch mode */
int i , len = cJSON_GetArraySize ( json ) ;
reply = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < len ; i + + ) {
cJSON * obj , * item = cJSON_GetArrayItem ( json , i ) ;
if ( ( obj = process_jrpc ( jsock , item ) ) ) {
cJSON_AddItemToArray ( reply , obj ) ;
}
}
} else {
reply = process_jrpc ( jsock , json ) ;
}
} else {
reply = jrpc_new ( 0 ) ;
jrpc_add_error ( reply , - 32600 , " Invalid Request " , NULL ) ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( reply ) {
ws_write_json ( jsock , & reply , SWITCH_TRUE ) ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( json ) {
cJSON_Delete ( json ) ;
}
return status ;
}
2014-07-18 01:03:57 +05:00
static void jsock_check_event_queue ( jsock_t * jsock )
{
void * pop ;
int this_pass = switch_queue_size ( jsock - > event_queue ) ;
switch_mutex_lock ( jsock - > write_mutex ) ;
while ( this_pass - - > 0 & & switch_queue_trypop ( jsock - > event_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
cJSON * json = ( cJSON * ) pop ;
ws_write_json ( jsock , & json , SWITCH_TRUE ) ;
}
switch_mutex_unlock ( jsock - > write_mutex ) ;
}
2014-09-04 10:24:19 +08:00
/* DO NOT use this unless you know what you are doing, you are WARNNED!!! */
static uint8_t * http_stream_read ( switch_stream_handle_t * handle , int * len )
{
2020-03-25 03:49:19 +04:00
kws_request_t * r = ( kws_request_t * ) handle - > data ;
2014-09-04 10:24:19 +08:00
jsock_t * jsock = r - > user_data ;
2020-03-25 03:49:19 +04:00
kws_t * wsh = jsock - > ws ;
uint8_t * buffer = NULL ;
2014-09-04 10:24:19 +08:00
2014-09-07 11:48:27 +08:00
if ( ! jsock - > profile - > running ) {
* len = 0 ;
return NULL ;
}
2020-03-25 03:49:19 +04:00
* len = HTTP_CHUNK_SIZE ;
if ( ( * len = ( int ) kws_read_buffer ( wsh , & buffer , * len , 1 ) ) < 0 ) {
2014-09-06 19:35:05 +08:00
* len = 0 ;
return NULL ;
}
2020-03-25 03:49:19 +04:00
return buffer ;
2014-09-04 10:24:19 +08:00
}
static switch_status_t http_stream_raw_write ( switch_stream_handle_t * handle , uint8_t * data , switch_size_t datalen )
{
2020-03-25 03:49:19 +04:00
kws_request_t * r = ( kws_request_t * ) handle - > data ;
2014-09-04 10:24:19 +08:00
jsock_t * jsock = r - > user_data ;
2020-03-25 03:49:19 +04:00
return kws_raw_write ( jsock - > ws , data , ( uint32_t ) datalen ) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE ;
2014-09-04 10:24:19 +08:00
}
static switch_status_t http_stream_write ( switch_stream_handle_t * handle , const char * fmt , . . . )
{
2020-03-25 03:49:19 +04:00
kws_request_t * r = ( kws_request_t * ) handle - > data ;
2014-09-04 10:24:19 +08:00
jsock_t * jsock = r - > user_data ;
int ret = 1 ;
char * data ;
va_list ap ;
va_start ( ap , fmt ) ;
ret = switch_vasprintf ( & data , fmt , ap ) ;
va_end ( ap ) ;
if ( data ) {
if ( ret ) {
2020-03-25 03:49:19 +04:00
ret = ( int ) kws_raw_write ( jsock - > ws , data , ( uint32_t ) strlen ( data ) ) ;
2014-09-04 10:24:19 +08:00
}
switch_safe_free ( data ) ;
}
return ret ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE ;
}
2020-03-25 03:49:19 +04:00
static void http_static_handler ( kws_request_t * request , verto_vhost_t * vhost )
2014-09-04 10:24:19 +08:00
{
jsock_t * jsock = request - > user_data ;
char path [ 512 ] ;
switch_file_t * fd ;
char * ext ;
uint8_t chunk [ 4096 ] ;
const char * mime_type = " text/html " , * new_type ;
2020-03-25 03:49:19 +04:00
switch_time_exp_t tm ;
char date [ 80 ] = " " ;
switch_time_t ts = switch_micro_time_now ( ) ;
switch_time_exp_lt ( & tm , ts ) ;
switch_rfc822_date ( date , ts ) ;
2014-09-04 10:24:19 +08:00
2014-09-06 17:20:58 +08:00
if ( strncmp ( request - > method , " GET " , 3 ) & & strncmp ( request - > method , " HEAD " , 4 ) ) {
char * data = " HTTP/1.1 415 Method Not Allowed \r \n "
2014-09-07 11:48:27 +08:00
" Content-Length: 0 \r \n \r \n " ;
2020-03-25 03:49:19 +04:00
kws_raw_write ( jsock - > ws , data , strlen ( data ) ) ;
2014-09-06 17:20:58 +08:00
return ;
}
2014-09-06 12:06:24 +08:00
switch_snprintf ( path , sizeof ( path ) , " %s%s " , vhost - > root , request - > uri ) ;
2014-09-04 10:24:19 +08:00
2014-09-06 12:06:24 +08:00
if ( switch_directory_exists ( path , NULL ) = = SWITCH_STATUS_SUCCESS ) {
switch_snprintf ( path , sizeof ( path ) , " %s%s%s%s " ,
vhost - > root , request - > uri , end_of ( path ) = = ' / ' ? " " : SWITCH_PATH_SEPARATOR , vhost - > index ) ;
// printf("local path: %s\n", path);
2014-09-04 10:24:19 +08:00
}
if ( ( ext = strrchr ( path , ' . ' ) ) ) {
ext + + ;
if ( ( new_type = switch_core_mime_ext2type ( ext ) ) ) {
mime_type = new_type ;
}
}
2014-09-06 12:06:24 +08:00
if ( switch_file_exists ( path , NULL ) = = SWITCH_STATUS_SUCCESS & &
switch_file_open ( & fd , path , SWITCH_FOPEN_READ , SWITCH_FPROT_UREAD , jsock - > pool ) = = SWITCH_STATUS_SUCCESS ) {
2014-09-06 17:20:58 +08:00
2014-09-04 10:24:19 +08:00
switch_size_t flen = switch_file_get_size ( fd ) ;
2014-09-06 17:20:58 +08:00
2014-09-04 10:24:19 +08:00
switch_snprintf ( ( char * ) chunk , sizeof ( chunk ) ,
" HTTP/1.1 200 OK \r \n "
" Date: %s \r \n "
" Server: FreeSWITCH-%s-mod_verto \r \n "
" Content-Type: %s \r \n "
" Content-Length: % " SWITCH_SIZE_T_FMT " \r \n \r \n " ,
2020-03-25 03:49:19 +04:00
date ,
2014-09-04 10:24:19 +08:00
switch_version_full ( ) ,
mime_type ,
flen ) ;
2020-03-25 03:49:19 +04:00
kws_raw_write ( jsock - > ws , chunk , strlen ( ( char * ) chunk ) ) ;
2014-09-04 10:24:19 +08:00
for ( ; ; ) {
switch_status_t status ;
flen = sizeof ( chunk ) ;
status = switch_file_read ( fd , chunk , & flen ) ;
if ( status ! = SWITCH_STATUS_SUCCESS | | flen = = 0 ) {
break ;
}
2020-03-25 03:49:19 +04:00
kws_raw_write ( jsock - > ws , chunk , flen ) ;
2014-09-04 10:24:19 +08:00
}
switch_file_close ( fd ) ;
} else {
char * data = " HTTP/1.1 404 Not Found \r \n "
2014-09-07 11:48:27 +08:00
" Content-Length: 0 \r \n \r \n " ;
2020-03-25 03:49:19 +04:00
kws_raw_write ( jsock - > ws , data , strlen ( data ) ) ;
}
}
static void request_headers_to_event ( switch_event_t * event , kws_request_t * request )
{
int i ;
for ( i = 0 ; i < KWS_MAX_HEADERS ; i + + ) {
if ( ! request - > headers_k [ i ] ) break ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , request - > headers_k [ i ] , request - > headers_v [ i ] ) ;
2014-09-04 10:24:19 +08:00
}
}
static void http_run ( jsock_t * jsock )
{
2020-03-25 03:49:19 +04:00
kws_request_t * request = NULL ;
2014-09-04 10:24:19 +08:00
switch_stream_handle_t stream = { 0 } ;
2015-08-31 17:08:52 -04:00
char * err = NULL ;
2014-09-06 12:06:24 +08:00
char * ext ;
verto_vhost_t * vhost ;
2020-03-25 03:49:19 +04:00
ks_bool_t keepalive ;
2014-09-07 11:48:27 +08:00
new_req :
2014-09-04 10:24:19 +08:00
if ( switch_event_create ( & stream . param_event , SWITCH_EVENT_CHANNEL_DATA ) ! = SWITCH_STATUS_SUCCESS ) {
goto err ;
}
2020-03-25 03:49:19 +04:00
if ( kws_parse_header ( jsock - > ws , & request ) ! = KS_STATUS_SUCCESS ) {
2014-09-04 10:24:19 +08:00
goto err ;
}
2020-03-25 03:49:19 +04:00
request - > user_data = jsock ;
2014-09-07 11:48:27 +08:00
2020-03-25 03:49:19 +04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s %s \n " , jsock - > name , request - > uri ) ;
if ( ! strncmp ( request - > method , " OPTIONS " , 7 ) ) {
2014-09-06 17:20:58 +08:00
char data [ 512 ] ;
switch_snprintf ( data , sizeof ( data ) ,
" HTTP/1.1 200 OK \r \n "
2014-09-07 11:48:27 +08:00
" Content-Length: 0 \r \n "
2014-09-06 17:20:58 +08:00
" Date: %s \r \n "
" Allow: HEAD,GET,POST,PUT,DELETE,PATCH,OPTIONS \r \n "
" Server: FreeSWITCH-%s-mod_verto \r \n \r \n " ,
2020-03-25 03:49:19 +04:00
switch_event_get_header ( stream . param_event , " Event-Date-GMT " ) ,
2014-09-06 17:20:58 +08:00
switch_version_full ( ) ) ;
2020-03-25 03:49:19 +04:00
kws_raw_write ( jsock - > ws , data , strlen ( data ) ) ;
2014-09-06 17:20:58 +08:00
goto done ;
}
2020-06-15 15:13:39 +04:00
if ( request - > content_length & & request - > content_length > INT32_MAX ) {
2020-03-25 03:49:19 +04:00
char * data = " HTTP/1.1 413 Request Entity Too Large \r \n "
" Content-Length: 0 \r \n \r \n " ;
kws_raw_write ( jsock - > ws , data , strlen ( data ) ) ;
request - > keepalive = 0 ;
goto done ;
}
if ( ! strncmp ( request - > method , " POST " , 4 ) & & request - > content_length & & request - > content_type & &
! strncmp ( request - > content_type , " application/x-www-form-urlencoded " , 33 ) ) {
2014-09-06 16:59:53 +08:00
char * buffer = NULL ;
2014-12-29 13:49:42 -05:00
switch_ssize_t len = 0 , bytes = 0 ;
2014-09-06 16:59:53 +08:00
2020-03-25 03:49:19 +04:00
if ( request - > content_length & & request - > content_length > 10 * 1024 * 1024 - 1 ) {
2014-09-06 16:59:53 +08:00
char * data = " HTTP/1.1 413 Request Entity Too Large \r \n "
2014-09-07 11:48:27 +08:00
" Content-Length: 0 \r \n \r \n " ;
2020-03-25 03:49:19 +04:00
kws_raw_write ( jsock - > ws , data , strlen ( data ) ) ;
request - > keepalive = 0 ;
2014-09-06 16:59:53 +08:00
goto done ;
}
if ( ! ( buffer = malloc ( 2 * 1024 * 1024 ) ) ) {
goto request_err ;
}
2020-03-25 03:49:19 +04:00
while ( bytes < ( switch_ssize_t ) request - > content_length ) {
len = request - > content_length - bytes ;
2014-09-06 16:59:53 +08:00
2020-03-25 03:49:19 +04:00
# define WS_BLOCK 1
2014-09-06 16:59:53 +08:00
2020-03-25 03:49:19 +04:00
if ( ( len = kws_raw_read ( jsock - > ws , buffer + bytes , len , WS_BLOCK ) ) < 0 ) {
2014-12-29 13:49:42 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Read error % " SWITCH_SSIZE_T_FMT " \n " , len ) ;
2014-09-06 16:59:53 +08:00
goto done ;
}
bytes + = len ;
}
* ( buffer + bytes ) = ' \0 ' ;
2020-03-25 03:49:19 +04:00
kws_parse_qs ( request , buffer ) ;
2014-09-06 16:59:53 +08:00
free ( buffer ) ;
}
2020-03-25 03:49:19 +04:00
// kws_request_dump(request);
2014-09-04 10:24:19 +08:00
2020-03-25 03:49:19 +04:00
stream . data = request ;
2014-09-04 10:24:19 +08:00
stream . read_function = http_stream_read ;
stream . write_function = http_stream_write ;
stream . raw_write_function = http_stream_raw_write ;
2020-03-25 03:49:19 +04:00
request_headers_to_event ( stream . param_event , request ) ;
2014-09-04 10:24:19 +08:00
2020-03-25 03:49:19 +04:00
switch_event_add_header_string ( stream . param_event , SWITCH_STACK_BOTTOM , " Request-Method " , request - > method ) ;
switch_event_add_header_string ( stream . param_event , SWITCH_STACK_BOTTOM , " HTTP-Request-URI " , request - > uri ) ;
2014-09-06 12:06:24 +08:00
if ( ! jsock - > profile - > vhosts ) goto err ;
/* only one vhost supported for now */
vhost = jsock - > profile - > vhosts ;
2014-09-06 14:29:51 +08:00
if ( ! switch_test_flag ( jsock , JPFLAG_AUTHED ) & & vhost - > auth_realm ) {
int code = CODE_AUTH_REQUIRED ;
char message [ 128 ] = " Authentication Required " ;
cJSON * params = NULL ;
2020-03-25 03:49:19 +04:00
const char * www_auth ;
2014-09-06 14:29:51 +08:00
char auth_buffer [ 512 ] ;
char * auth_user = NULL , * auth_pass = NULL ;
2020-03-25 03:49:19 +04:00
www_auth = request - > authorization ;
2014-09-06 14:29:51 +08:00
if ( zstr ( www_auth ) ) {
switch_snprintf ( auth_buffer , sizeof ( auth_buffer ) ,
" HTTP/1.1 401 Authentication Required \r \n "
" WWW-Authenticate: Basic realm= \" %s \" \r \n "
2014-09-07 11:48:27 +08:00
" Content-Length: 0 \r \n \r \n " ,
2014-09-06 14:29:51 +08:00
vhost - > auth_realm ) ;
2020-03-25 03:49:19 +04:00
kws_raw_write ( jsock - > ws , auth_buffer , strlen ( auth_buffer ) ) ;
2014-09-06 14:29:51 +08:00
goto done ;
}
if ( strncasecmp ( www_auth , " Basic " , 6 ) ) goto err ;
www_auth + = 6 ;
switch_b64_decode ( www_auth , auth_buffer , sizeof ( auth_buffer ) ) ;
auth_user = auth_buffer ;
if ( ( auth_pass = strchr ( auth_user , ' : ' ) ) ) {
* auth_pass + + = ' \0 ' ;
}
2020-02-25 21:18:44 +00:00
if ( vhost - > auth_user & & vhost - > auth_pass & & auth_pass & &
2014-09-06 14:29:51 +08:00
! strcmp ( vhost - > auth_user , auth_user ) & &
! strcmp ( vhost - > auth_pass , auth_pass ) ) {
goto authed ;
}
if ( ! ( params = cJSON_CreateObject ( ) ) ) {
2014-09-06 16:59:53 +08:00
goto request_err ;
2014-09-06 14:29:51 +08:00
}
cJSON_AddItemToObject ( params , " login " , cJSON_CreateString ( auth_user ) ) ;
cJSON_AddItemToObject ( params , " passwd " , cJSON_CreateString ( auth_pass ) ) ;
if ( ! check_auth ( jsock , params , & code , message , sizeof ( message ) ) ) {
switch_snprintf ( auth_buffer , sizeof ( auth_buffer ) ,
" HTTP/1.1 401 Authentication Required \r \n "
" WWW-Authenticate: Basic realm= \" %s \" \r \n "
2014-09-07 11:48:27 +08:00
" Content-Length: 0 \r \n \r \n " ,
2014-09-06 14:29:51 +08:00
vhost - > auth_realm ) ;
2020-03-25 03:49:19 +04:00
kws_raw_write ( jsock - > ws , auth_buffer , strlen ( auth_buffer ) ) ;
2014-09-06 14:29:51 +08:00
cJSON_Delete ( params ) ;
goto done ;
} else {
cJSON_Delete ( params ) ;
}
authed :
switch_set_flag ( jsock , JPFLAG_AUTHED ) ;
2020-03-25 03:49:19 +04:00
switch_event_add_header_string ( stream . param_event , SWITCH_STACK_BOTTOM , " HTTP-USER " , auth_user ) ;
2014-09-06 14:29:51 +08:00
}
2014-09-06 12:06:24 +08:00
if ( vhost - > rewrites ) {
switch_event_header_t * rule = vhost - > rewrites - > headers ;
switch_regex_t * re = NULL ;
int ovector [ 30 ] ;
int proceed ;
while ( rule ) {
char * expression = rule - > name ;
2020-03-25 03:49:19 +04:00
if ( ( proceed = switch_regex_perform ( request - > uri , expression , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ) ) {
2015-01-27 23:17:43 +08:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
2020-03-25 03:49:19 +04:00
" %d request [%s] matched expr [%s] \n " , proceed , request - > uri , expression ) ;
request - > uri = rule - > value ;
2023-11-03 17:27:06 +01:00
switch_regex_safe_free ( re ) ;
2014-09-06 12:06:24 +08:00
break ;
}
rule = rule - > next ;
2023-11-03 17:27:06 +01:00
switch_regex_safe_free ( re ) ;
2014-09-06 12:06:24 +08:00
}
}
2020-03-25 03:49:19 +04:00
switch_event_add_header_string ( stream . param_event , SWITCH_STACK_BOTTOM , " HTTP-URI " , request - > uri ) ;
2014-09-04 10:24:19 +08:00
2020-03-25 03:49:19 +04:00
if ( ( ext = strrchr ( request - > uri , ' . ' ) ) ) {
2014-09-06 12:06:24 +08:00
char path [ 1024 ] ;
if ( ! strncmp ( ext , " .lua " , 4 ) ) {
2020-03-25 03:49:19 +04:00
switch_snprintf ( path , sizeof ( path ) , " %s%s " , vhost - > script_root , request - > uri ) ;
2014-09-06 12:06:24 +08:00
switch_api_execute ( " lua " , path , NULL , & stream ) ;
} else {
2020-03-25 03:49:19 +04:00
http_static_handler ( request , vhost ) ;
2014-09-06 12:06:24 +08:00
}
2014-09-04 10:24:19 +08:00
} else {
2020-03-25 03:49:19 +04:00
http_static_handler ( request , vhost ) ;
2014-09-04 10:24:19 +08:00
}
2014-09-06 14:29:51 +08:00
done :
2020-03-25 03:49:19 +04:00
keepalive = request - > keepalive ;
kws_request_free ( & request ) ;
2021-10-24 20:39:56 +08:00
if ( stream . param_event ) switch_event_destroy ( & stream . param_event ) ;
2014-09-07 11:48:27 +08:00
if ( keepalive ) {
2020-03-25 03:49:19 +04:00
kws_t * wsh = jsock - > ws ;
2014-09-07 11:48:27 +08:00
while ( jsock - > profile - > running ) {
2020-07-09 23:06:47 +04:00
int pflags = kws_wait_sock ( wsh , 3000 , KS_POLL_READ ) ;
2014-09-07 11:48:27 +08:00
if ( jsock - > drop ) { die ( " %s Dropping Connection \n " , jsock - > name ) ; }
2018-10-18 04:52:14 -07:00
if ( pflags < 0 & & ( errno ! = EINTR ) ) { die_errnof ( " %s POLL FAILED with %d " , jsock - > name , pflags ) ; }
2018-10-18 04:54:18 -07:00
if ( pflags = = 0 ) { /* keepalive socket poll timeout */ break ; }
2020-03-25 03:49:19 +04:00
if ( pflags > 0 & & ( pflags & KS_POLL_HUP ) ) { log_and_exit ( SWITCH_LOG_INFO , " %s POLL HANGUP DETECTED (peer closed its end of socket) \n " , jsock - > name ) ; }
if ( pflags > 0 & & ( pflags & KS_POLL_ERROR ) ) { die ( " %s POLL ERROR \n " , jsock - > name ) ; }
if ( pflags > 0 & & ( pflags & KS_POLL_INVALID ) ) { die ( " %s POLL INVALID SOCKET (not opened or already closed) \n " , jsock - > name ) ; }
if ( pflags > 0 & & ( pflags & KS_POLL_READ ) ) {
if ( kws_keepalive ( wsh ) = = KS_STATUS_SUCCESS ) {
2014-09-07 11:48:27 +08:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " socket %s is going to handle a new request \n " , jsock - > name ) ;
goto new_req ;
2020-03-25 03:49:19 +04:00
} else {
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Read Error\n");
break ;
2014-09-07 11:48:27 +08:00
}
2020-03-25 03:49:19 +04:00
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " unhandled flag: %d \n " , pflags ) ;
2014-09-07 11:48:27 +08:00
}
}
}
2014-09-04 10:24:19 +08:00
return ;
2014-09-06 16:59:53 +08:00
request_err :
2020-03-25 03:49:19 +04:00
kws_request_free ( & request ) ;
2014-09-06 16:59:53 +08:00
2014-09-04 10:24:19 +08:00
err :
2015-08-31 17:08:52 -04:00
err = " HTTP/1.1 500 Internal Server Error \r \n "
2014-09-07 11:48:27 +08:00
" Content-Length: 0 \r \n \r \n " ;
2020-03-25 03:49:19 +04:00
kws_raw_write ( jsock - > ws , err , strlen ( err ) ) ;
2014-09-07 11:48:27 +08:00
error :
return ;
2014-09-04 10:24:19 +08:00
}
2014-06-11 12:48:46 -05:00
static void client_run ( jsock_t * jsock )
{
2020-03-25 03:49:19 +04:00
int flags = KWS_BLOCK ;
2020-05-10 21:32:13 +00:00
int idle = 0 ;
2023-01-16 18:52:26 +03:00
ks_json_t * params = NULL ;
2020-05-10 21:32:13 +00:00
2020-03-25 03:49:19 +04:00
if ( jsock - > profile - > vhosts ) {
flags | = KWS_STAY_OPEN ;
flags | = KWS_HTTP ;
}
ks_pool_open ( & jsock - > kpool ) ;
2023-01-16 18:52:26 +03:00
# if defined(KS_VERSION_NUM) && KS_VERSION_NUM >= 20000
params = ks_json_create_object ( ) ;
ks_json_add_number_to_object ( params , " payload_size_max " , 1000000 ) ;
if ( kws_init_ex ( & jsock - > ws , jsock - > client_socket , ( jsock - > ptype & PTYPE_CLIENT_SSL ) ? jsock - > profile - > ssl_ctx : NULL , 0 , flags , jsock - > kpool , params ) ! = KS_STATUS_SUCCESS ) {
# else
2020-03-25 03:49:19 +04:00
if ( kws_init ( & jsock - > ws , jsock - > client_socket , ( jsock - > ptype & PTYPE_CLIENT_SSL ) ? jsock - > profile - > ssl_ctx : NULL , 0 , flags , jsock - > kpool ) ! = KS_STATUS_SUCCESS ) {
2023-01-16 18:52:26 +03:00
# endif
2020-03-25 03:49:19 +04:00
log_and_exit ( SWITCH_LOG_NOTICE , " %s WS SETUP FAILED \n " , jsock - > name ) ;
}
if ( kws_test_flag ( jsock - > ws , KWS_HTTP ) ) {
http_run ( jsock ) ;
kws_close ( jsock - > ws , WS_NONE ) ;
goto end ;
2014-06-11 12:48:46 -05:00
}
while ( jsock - > profile - > running ) {
2020-05-10 21:32:13 +00:00
int pflags , poll_time = 50 ;
2021-02-03 21:18:07 +00:00
time_t now ;
2019-02-26 14:07:40 -07:00
2020-03-25 03:49:19 +04:00
if ( ! jsock - > ws ) { die ( " %s Setup Error \n " , jsock - > name ) ; }
2020-07-09 23:06:47 +04:00
pflags = kws_wait_sock ( jsock - > ws , poll_time , KS_POLL_READ ) ;
2014-06-11 12:48:46 -05:00
2021-02-03 21:18:07 +00:00
if ( jsock - > exptime ) {
now = switch_epoch_time_now ( NULL ) ;
if ( now > = jsock - > exptime ) {
2021-03-31 20:13:38 +00:00
switch_set_flag ( jsock , JPFLAG_AUTH_EXPIRED ) ;
2021-04-02 23:02:38 +00:00
die ( " %s Authentication Expired [%ld] >= [%ld] \n " , jsock - > uid , now , jsock - > exptime ) ;
2021-02-03 21:18:07 +00:00
}
}
2018-08-29 03:36:50 -07:00
if ( jsock - > drop ) { die ( " %s Dropping Connection \n " , jsock - > name ) ; }
2018-10-18 04:52:14 -07:00
if ( pflags < 0 & & ( errno ! = EINTR ) ) { die_errnof ( " %s POLL FAILED with %d " , jsock - > name , pflags ) ; }
2020-05-10 21:32:13 +00:00
if ( pflags = = 0 ) { /* socket poll timeout */ jsock_check_event_queue ( jsock ) ; idle + = poll_time ; } else { idle = 0 ; }
if ( idle > = 30000 ) {
cJSON * params = NULL ;
cJSON * msg = jrpc_new_req ( " verto.ping " , 0 , & params ) ;
2020-04-13 23:17:37 +00:00
2021-03-31 20:13:38 +00:00
if ( jsock - > exptime ) {
cJSON_AddItemToObject ( params , " auth-expires " , cJSON_CreateNumber ( jsock - > exptime ) ) ;
}
2020-05-10 21:32:13 +00:00
cJSON_AddItemToObject ( params , " serno " , cJSON_CreateNumber ( switch_epoch_time_now ( NULL ) ) ) ;
jsock_queue_event ( jsock , & msg , SWITCH_TRUE ) ;
idle = 0 ;
}
2020-04-13 23:17:37 +00:00
if ( ( ! switch_test_flag ( jsock , JPFLAG_CHECK_ATTACH ) | | ( jsock - > attach_timer > 0 & & jsock - > attach_timer - - = = 0 ) ) & &
switch_test_flag ( jsock , JPFLAG_AUTHED ) ) {
attach_calls ( jsock ) ;
switch_set_flag ( jsock , JPFLAG_CHECK_ATTACH ) ;
}
2020-03-25 03:49:19 +04:00
if ( pflags > 0 & & ( pflags & KS_POLL_HUP ) ) { log_and_exit ( SWITCH_LOG_INFO , " %s POLL HANGUP DETECTED (peer closed its end of socket) \n " , jsock - > name ) ; }
if ( pflags > 0 & & ( pflags & KS_POLL_ERROR ) ) { die ( " %s POLL ERROR \n " , jsock - > name ) ; }
if ( pflags > 0 & & ( pflags & KS_POLL_INVALID ) ) { die ( " %s POLL INVALID SOCKET (not opened or already closed) \n " , jsock - > name ) ; }
if ( pflags > 0 & & ( pflags & KS_POLL_READ ) ) {
2014-06-11 12:48:46 -05:00
switch_ssize_t bytes ;
2020-03-25 03:49:19 +04:00
kws_opcode_t oc ;
2014-06-11 12:48:46 -05:00
uint8_t * data ;
2017-01-06 02:10:15 -05:00
2020-03-25 03:49:19 +04:00
bytes = kws_read_frame ( jsock - > ws , & oc , & data ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( bytes < 0 ) {
2020-03-25 03:49:19 +04:00
if ( bytes = = - 1000 ) {
2018-10-18 04:52:14 -07:00
log_and_exit ( SWITCH_LOG_INFO , " %s Client sent close request \n " , jsock - > name ) ;
2018-08-29 03:36:50 -07:00
} else {
die ( " %s BAD READ % " SWITCH_SSIZE_T_FMT " \n " , jsock - > name , bytes ) ;
}
2014-06-11 12:48:46 -05:00
}
if ( bytes ) {
2015-10-03 02:36:28 -05:00
char * s = ( char * ) data ;
if ( * s = = ' # ' ) {
2015-10-03 13:34:09 -05:00
char repl [ 2048 ] = " " ;
2015-10-03 02:36:28 -05:00
switch_time_t a , b ;
2017-01-06 02:10:15 -05:00
2015-10-03 02:36:28 -05:00
if ( s [ 1 ] = = ' S ' & & s [ 2 ] = = ' P ' ) {
if ( s [ 3 ] = = ' U ' ) {
2015-10-03 13:34:09 -05:00
int i , size = 0 ;
char * p = s + 4 ;
int loops = 0 ;
int rem = 0 ;
2015-10-05 13:00:33 -05:00
int dur = 0 , j = 0 ;
2015-10-03 13:34:09 -05:00
2019-10-23 23:03:18 +04:00
if ( ( size = atoi ( p ) ) < = 0 ) {
2015-10-03 13:34:09 -05:00
continue ;
}
2017-01-06 02:10:15 -05:00
2015-10-03 02:36:28 -05:00
a = switch_time_now ( ) ;
2015-10-03 13:34:09 -05:00
do {
2020-03-25 03:49:19 +04:00
bytes = kws_read_frame ( jsock - > ws , & oc , & data ) ;
2015-10-03 13:34:09 -05:00
s = ( char * ) data ;
} while ( bytes & & data & & s [ 0 ] = = ' # ' & & s [ 3 ] = = ' B ' ) ;
2015-10-03 02:36:28 -05:00
b = switch_time_now ( ) ;
if ( ! bytes | | ! data ) continue ;
2017-01-06 02:10:15 -05:00
2015-10-03 13:34:09 -05:00
if ( s [ 0 ] ! = ' # ' ) goto nm ;
2015-12-14 14:23:31 -06:00
switch_snprintf ( repl , sizeof ( repl ) , " #SPU %ld " , ( long ) ( ( b - a ) / 1000 ) ) ;
2020-03-25 03:49:19 +04:00
kws_write_frame ( jsock - > ws , WSOC_TEXT , repl , strlen ( repl ) ) ;
2015-10-03 13:34:09 -05:00
loops = size / 1024 ;
rem = size % 1024 ;
switch_snprintf ( repl , sizeof ( repl ) , " #SPB " ) ;
memset ( repl + 4 , ' . ' , 1024 ) ;
2015-10-05 13:00:33 -05:00
for ( j = 0 ; j < 10 ; j + + ) {
int ddur = 0 ;
a = switch_time_now ( ) ;
for ( i = 0 ; i < loops ; i + + ) {
2020-03-25 03:49:19 +04:00
kws_write_frame ( jsock - > ws , WSOC_TEXT , repl , 1024 ) ;
2015-10-05 13:00:33 -05:00
}
if ( rem ) {
2020-03-25 03:49:19 +04:00
kws_write_frame ( jsock - > ws , WSOC_TEXT , repl , rem ) ;
2015-10-05 13:00:33 -05:00
}
b = switch_time_now ( ) ;
2015-12-14 14:23:31 -06:00
ddur + = ( int ) ( ( b - a ) / 1000 ) ;
2015-10-05 13:00:33 -05:00
dur + = ddur ;
2015-10-03 13:34:09 -05:00
}
2015-10-03 02:36:28 -05:00
2015-10-05 13:00:33 -05:00
dur / = j + 1 ;
switch_snprintf ( repl , sizeof ( repl ) , " #SPD %d " , dur ) ;
2020-03-25 03:49:19 +04:00
kws_write_frame ( jsock - > ws , WSOC_TEXT , repl , strlen ( repl ) ) ;
2015-10-03 02:36:28 -05:00
}
}
continue ;
}
2015-10-03 13:34:09 -05:00
nm :
2015-10-03 02:36:28 -05:00
2014-06-11 12:48:46 -05:00
if ( process_input ( jsock , data , bytes ) ! = SWITCH_STATUS_SUCCESS ) {
2018-08-29 03:36:50 -07:00
die ( " %s Input Error \n " , jsock - > name ) ;
2014-06-11 12:48:46 -05:00
}
}
}
}
error :
2020-03-25 03:49:19 +04:00
end :
2014-06-11 12:48:46 -05:00
detach_jsock ( jsock ) ;
2020-03-25 03:49:19 +04:00
kws_destroy ( & jsock - > ws ) ;
ks_pool_close ( & jsock - > kpool ) ;
2023-01-16 18:52:26 +03:00
ks_json_delete ( & params ) ;
2014-06-11 12:48:46 -05:00
return ;
}
2014-07-18 01:03:57 +05:00
static void jsock_flush ( jsock_t * jsock )
{
void * pop ;
switch_mutex_lock ( jsock - > write_mutex ) ;
while ( switch_queue_trypop ( jsock - > event_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
cJSON * json = ( cJSON * ) pop ;
cJSON_Delete ( json ) ;
}
switch_mutex_unlock ( jsock - > write_mutex ) ;
}
2014-06-11 12:48:46 -05:00
static void * SWITCH_THREAD_FUNC client_thread ( switch_thread_t * thread , void * obj )
{
2014-08-01 23:07:13 +05:00
switch_event_t * s_event ;
2014-06-11 12:48:46 -05:00
jsock_t * jsock = ( jsock_t * ) obj ;
switch_event_create ( & jsock - > params , SWITCH_EVENT_CHANNEL_DATA ) ;
switch_event_create ( & jsock - > vars , SWITCH_EVENT_CHANNEL_DATA ) ;
2015-04-25 10:57:09 -05:00
switch_event_create ( & jsock - > user_vars , SWITCH_EVENT_CHANNEL_DATA ) ;
2014-06-11 12:48:46 -05:00
add_jsock ( jsock ) ;
2016-09-20 14:03:35 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s Starting client thread. \n " , jsock - > name ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ( jsock - > ptype & PTYPE_CLIENT ) | | ( jsock - > ptype & PTYPE_CLIENT_SSL ) ) {
client_run ( jsock ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " %s Ending client thread. \n " , jsock - > name ) ;
}
detach_calls ( jsock ) ;
del_jsock ( jsock ) ;
switch_event_destroy ( & jsock - > params ) ;
switch_event_destroy ( & jsock - > vars ) ;
2015-04-25 10:57:09 -05:00
switch_event_destroy ( & jsock - > user_vars ) ;
2014-06-11 12:48:46 -05:00
2020-03-25 03:49:19 +04:00
if ( jsock - > client_socket ! = KS_SOCK_INVALID ) {
2014-06-11 12:48:46 -05:00
close_socket ( & jsock - > client_socket ) ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_event_destroy ( & jsock - > allowed_methods ) ;
switch_event_destroy ( & jsock - > allowed_fsapi ) ;
switch_event_destroy ( & jsock - > allowed_jsapi ) ;
switch_event_destroy ( & jsock - > allowed_event_channels ) ;
2014-07-18 01:03:57 +05:00
jsock_flush ( jsock ) ;
2014-06-11 12:48:46 -05:00
2016-09-20 14:03:35 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s Ending client thread. \n " , jsock - > name ) ;
2014-08-01 23:07:13 +05:00
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_CLIENT_DISCONNECT ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " verto_profile_name " , jsock - > profile - > name ) ;
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " verto_client_address " , jsock - > name ) ;
2016-03-29 17:39:40 -03:00
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " verto_login " , switch_str_nil ( jsock - > uid ) ) ;
2014-08-01 23:07:13 +05:00
switch_event_fire ( & s_event ) ;
}
2014-06-11 12:48:46 -05:00
switch_thread_rwlock_wrlock ( jsock - > rwlock ) ;
2016-09-20 14:03:35 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s Thread ended \n " , jsock - > name ) ;
2014-06-11 12:48:46 -05:00
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
return NULL ;
}
static switch_bool_t auth_api_command ( jsock_t * jsock , const char * api_cmd , const char * arg )
{
const char * check_cmd = api_cmd ;
char * sneaky_commands [ ] = { " bgapi " , " sched_api " , " eval " , " expand " , " xml_wrap " , NULL } ;
int x = 0 ;
char * dup_arg = NULL ;
char * next = NULL ;
switch_bool_t ok = SWITCH_TRUE ;
top :
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! jsock - > allowed_fsapi ) {
ok = SWITCH_FALSE ;
goto end ;
}
if ( ! switch_event_get_header ( jsock - > allowed_fsapi , check_cmd ) ) {
ok = SWITCH_FALSE ;
goto end ;
}
while ( check_cmd ) {
for ( x = 0 ; sneaky_commands [ x ] ; x + + ) {
if ( ! strcasecmp ( sneaky_commands [ x ] , check_cmd ) ) {
if ( check_cmd = = api_cmd ) {
if ( arg ) {
switch_safe_free ( dup_arg ) ;
dup_arg = strdup ( arg ) ;
2019-07-12 19:59:40 +04:00
switch_assert ( dup_arg ) ;
2014-06-11 12:48:46 -05:00
check_cmd = dup_arg ;
if ( ( next = strchr ( check_cmd , ' ' ) ) ) {
* next + + = ' \0 ' ;
}
} else {
break ;
}
} else {
if ( next ) {
check_cmd = next ;
} else {
check_cmd = dup_arg ;
}
if ( ( next = strchr ( check_cmd , ' ' ) ) ) {
* next + + = ' \0 ' ;
}
}
goto top ;
}
}
break ;
}
end :
switch_safe_free ( dup_arg ) ;
return ok ;
}
//// VERTO
static void track_pvt ( verto_pvt_t * tech_pvt )
{
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_wrlock ( verto_globals . tech_rwlock ) ;
tech_pvt - > next = verto_globals . tech_head ;
verto_globals . tech_head = tech_pvt ;
2018-01-12 00:40:50 -06:00
switch_set_flag ( tech_pvt , TFLAG_TRACKED ) ;
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_unlock ( verto_globals . tech_rwlock ) ;
2014-06-11 12:48:46 -05:00
}
static void untrack_pvt ( verto_pvt_t * tech_pvt )
{
verto_pvt_t * p , * last = NULL ;
2017-02-09 17:39:35 -06:00
int wake = 0 ;
2018-01-12 00:40:50 -06:00
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_wrlock ( verto_globals . tech_rwlock ) ;
2018-01-12 00:40:50 -06:00
2014-06-11 12:48:46 -05:00
if ( tech_pvt - > detach_time ) {
2017-02-09 17:23:30 -06:00
verto_globals . detached - - ;
2014-06-11 12:48:46 -05:00
tech_pvt - > detach_time = 0 ;
2017-02-09 17:39:35 -06:00
wake = 1 ;
2014-06-11 12:48:46 -05:00
}
2018-01-12 00:40:50 -06:00
if ( switch_test_flag ( tech_pvt , TFLAG_TRACKED ) ) {
switch_clear_flag ( tech_pvt , TFLAG_TRACKED ) ;
for ( p = verto_globals . tech_head ; p ; p = p - > next ) {
if ( p = = tech_pvt ) {
if ( last ) {
last - > next = p - > next ;
} else {
verto_globals . tech_head = p - > next ;
}
break ;
2014-06-11 12:48:46 -05:00
}
2018-01-12 00:40:50 -06:00
last = p ;
}
2014-06-11 12:48:46 -05:00
}
2018-01-12 00:40:50 -06:00
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_unlock ( verto_globals . tech_rwlock ) ;
2017-02-09 17:39:35 -06:00
if ( wake ) attach_wake ( ) ;
2014-06-11 12:48:46 -05:00
}
2015-09-23 10:35:45 -05:00
switch_endpoint_interface_t * verto_endpoint_interface = NULL ;
static switch_status_t verto_on_destroy ( switch_core_session_t * session )
{
2016-07-10 22:25:14 -05:00
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
switch_buffer_destroy ( & tech_pvt - > text_read_buffer ) ;
switch_buffer_destroy ( & tech_pvt - > text_write_buffer ) ;
2015-09-23 10:35:45 -05:00
UNPROTECT_INTERFACE ( verto_endpoint_interface ) ;
return SWITCH_STATUS_SUCCESS ;
}
2014-06-11 12:48:46 -05:00
static switch_status_t verto_on_hangup ( switch_core_session_t * session )
{
jsock_t * jsock = NULL ;
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
untrack_pvt ( tech_pvt ) ;
// get the jsock and send hangup notice
if ( ! tech_pvt - > remote_hangup_cause & & ( jsock = get_jsock ( tech_pvt - > jsock_uuid ) ) ) {
2014-07-14 21:25:43 +05:00
cJSON * params = NULL ;
cJSON * msg = jrpc_new_req ( " verto.bye " , tech_pvt - > call_id , & params ) ;
switch_call_cause_t cause = switch_channel_get_cause ( tech_pvt - > channel ) ;
2016-04-15 16:54:38 -03:00
switch_channel_set_variable ( tech_pvt - > channel , " verto_hangup_disposition " , " send_bye " ) ;
2014-07-14 21:25:43 +05:00
cJSON_AddItemToObject ( params , " causeCode " , cJSON_CreateNumber ( cause ) ) ;
cJSON_AddItemToObject ( params , " cause " , cJSON_CreateString ( switch_channel_cause2str ( cause ) ) ) ;
2014-07-26 02:24:10 +05:00
jsock_queue_event ( jsock , & msg , SWITCH_TRUE ) ;
2014-06-11 12:48:46 -05:00
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
}
return SWITCH_STATUS_SUCCESS ;
}
2018-01-12 00:40:50 -06:00
static switch_status_t verto_set_media_options ( verto_pvt_t * tech_pvt , verto_profile_t * profile ) ;
2014-06-11 12:48:46 -05:00
static switch_status_t verto_connect ( switch_core_session_t * session , const char * method )
{
switch_status_t status = SWITCH_STATUS_SUCCESS ;
jsock_t * jsock = NULL ;
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
2020-04-25 01:35:59 +00:00
2014-06-11 12:48:46 -05:00
if ( ! ( jsock = get_jsock ( tech_pvt - > jsock_uuid ) ) ) {
status = SWITCH_STATUS_BREAK ;
} else {
cJSON * params = NULL ;
cJSON * msg = NULL ;
const char * var = NULL ;
switch_caller_profile_t * caller_profile = switch_channel_get_caller_profile ( tech_pvt - > channel ) ;
2020-04-25 01:35:59 +00:00
switch_event_header_t * hi ;
2014-06-11 12:48:46 -05:00
2015-04-25 10:57:09 -05:00
//DUMP_EVENT(jsock->params);
2014-06-11 12:48:46 -05:00
switch_channel_set_variable ( tech_pvt - > channel , " verto_user " , jsock - > uid ) ;
2014-07-24 10:13:32 +05:00
switch_channel_set_variable ( tech_pvt - > channel , " presence_id " , jsock - > uid ) ;
2016-03-30 11:42:43 +02:00
switch_channel_set_variable ( tech_pvt - > channel , " verto_client_address " , jsock - > name ) ;
2014-07-24 10:13:32 +05:00
switch_channel_set_variable ( tech_pvt - > channel , " chat_proto " , VERTO_CHAT_PROTO ) ;
2014-06-11 12:48:46 -05:00
switch_channel_set_variable ( tech_pvt - > channel , " verto_host " , jsock - > domain ) ;
2021-01-24 19:08:44 +00:00
switch_mutex_lock ( jsock - > flag_mutex ) ;
2020-04-25 01:35:59 +00:00
for ( hi = jsock - > user_vars - > headers ; hi ; hi = hi - > next ) {
switch_channel_set_variable ( tech_pvt - > channel , hi - > name , hi - > value ) ;
2015-04-25 10:57:09 -05:00
}
2021-01-24 19:08:44 +00:00
switch_mutex_unlock ( jsock - > flag_mutex ) ;
2014-06-11 12:48:46 -05:00
if ( ( var = switch_event_get_header ( jsock - > params , " caller-id-name " ) ) ) {
caller_profile - > callee_id_name = switch_core_strdup ( caller_profile - > pool , var ) ;
}
if ( ( var = switch_event_get_header ( jsock - > params , " caller-id-number " ) ) ) {
caller_profile - > callee_id_number = switch_core_strdup ( caller_profile - > pool , var ) ;
}
if ( switch_channel_test_flag ( tech_pvt - > channel , CF_PROXY_MODE ) ) {
switch_core_media_absorb_sdp ( session ) ;
} else {
switch_channel_set_variable ( tech_pvt - > channel , " media_webrtc " , " true " ) ;
switch_core_session_set_ice ( tech_pvt - > session ) ;
2018-01-12 00:40:50 -06:00
if ( verto_set_media_options ( tech_pvt , jsock - > profile ) ! = SWITCH_STATUS_SUCCESS ) {
status = SWITCH_STATUS_FALSE ;
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
return status ;
}
2014-06-11 12:48:46 -05:00
2014-06-13 01:49:10 -04:00
2014-06-11 12:48:46 -05:00
switch_channel_set_variable ( tech_pvt - > channel , " verto_profile_name " , jsock - > profile - > name ) ;
if ( ! switch_channel_test_flag ( tech_pvt - > channel , CF_RECOVERING ) ) {
2017-12-06 14:36:19 +01:00
switch_channel_set_variable ( tech_pvt - > channel , " codec_string " , NULL ) ;
2014-06-13 01:49:10 -04:00
switch_core_media_prepare_codecs ( tech_pvt - > session , SWITCH_TRUE ) ;
2014-06-11 12:48:46 -05:00
if ( ( status = switch_core_media_choose_ports ( tech_pvt - > session , SWITCH_TRUE , SWITCH_TRUE ) ) ! = SWITCH_STATUS_SUCCESS ) {
//if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
return status ;
}
}
2017-01-06 02:10:15 -05:00
2023-10-18 20:24:14 +03:00
switch_core_media_gen_local_sdp ( session , SDP_OFFER , NULL , 0 , NULL , 0 ) ;
2014-06-11 12:48:46 -05:00
}
msg = jrpc_new_req ( method , tech_pvt - > call_id , & params ) ;
2017-01-06 02:10:15 -05:00
2020-04-25 01:35:59 +00:00
add_variables ( tech_pvt , params ) ;
2014-06-11 12:48:46 -05:00
if ( tech_pvt - > mparams - > local_sdp_str ) {
2017-01-06 02:10:15 -05:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Local %s SDP %s: \n %s \n " ,
2014-06-11 12:48:46 -05:00
method ,
switch_channel_get_name ( tech_pvt - > channel ) ,
tech_pvt - > mparams - > local_sdp_str ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
cJSON_AddItemToObject ( params , " sdp " , cJSON_CreateString ( tech_pvt - > mparams - > local_sdp_str ) ) ;
set_call_params ( params , tech_pvt ) ;
2017-01-06 02:10:15 -05:00
2014-07-26 02:24:10 +05:00
jsock_queue_event ( jsock , & msg , SWITCH_TRUE ) ;
2014-06-11 12:48:46 -05:00
} else {
status = SWITCH_STATUS_FALSE ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
return status ;
}
switch_status_t verto_tech_media ( verto_pvt_t * tech_pvt , const char * r_sdp , switch_sdp_type_t sdp_type )
{
2022-01-07 15:36:46 +03:00
uint8_t p = 0 ;
2014-06-11 12:48:46 -05:00
switch_assert ( tech_pvt ! = NULL ) ;
switch_assert ( r_sdp ! = NULL ) ;
if ( zstr ( r_sdp ) ) {
return SWITCH_STATUS_FALSE ;
}
2022-01-07 15:36:46 +03:00
if ( switch_core_media_negotiate_sdp ( tech_pvt - > session , r_sdp , & p , sdp_type ) ) {
2014-06-11 12:48:46 -05:00
if ( switch_core_media_choose_ports ( tech_pvt - > session , SWITCH_TRUE , SWITCH_FALSE ) ! = SWITCH_STATUS_SUCCESS ) {
//if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE ;
}
if ( switch_core_media_activate_rtp ( tech_pvt - > session ) ! = SWITCH_STATUS_SUCCESS ) {
return SWITCH_STATUS_FALSE ;
}
//if (!switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED)) {
// switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA");
// switch_channel_mark_pre_answered(tech_pvt->channel);
//}
return SWITCH_STATUS_SUCCESS ;
}
return SWITCH_STATUS_FALSE ;
}
static switch_status_t verto_on_init ( switch_core_session_t * session )
{
switch_status_t status = SWITCH_STATUS_SUCCESS ;
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
2014-08-19 03:25:24 +05:00
2014-06-11 12:48:46 -05:00
if ( switch_channel_test_flag ( tech_pvt - > channel , CF_RECOVERING_BRIDGE ) | | switch_channel_test_flag ( tech_pvt - > channel , CF_RECOVERING ) ) {
int tries = 120 ;
2014-08-19 03:25:24 +05:00
2014-06-11 12:48:46 -05:00
switch_core_session_clear_crypto ( session ) ;
while ( - - tries > 0 ) {
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
status = verto_connect ( session , " verto.attach " ) ;
if ( status = = SWITCH_STATUS_SUCCESS ) {
switch_set_flag ( tech_pvt , TFLAG_ATTACH_REQ ) ;
break ;
} else if ( status = = SWITCH_STATUS_BREAK ) {
switch_yield ( 1000000 ) ;
continue ;
} else {
tries = 0 ;
break ;
}
}
if ( ! tries ) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
status = SWITCH_STATUS_FALSE ;
}
switch_channel_set_flag ( tech_pvt - > channel , CF_VIDEO_BREAK ) ;
switch_core_session_kill_channel ( tech_pvt - > session , SWITCH_SIG_BREAK ) ;
tries = 500 ;
while ( - - tries > 0 & & switch_test_flag ( tech_pvt , TFLAG_ATTACH_REQ ) ) {
switch_yield ( 10000 ) ;
}
2014-12-03 20:34:49 -06:00
switch_core_session_request_video_refresh ( session ) ;
2014-06-11 12:48:46 -05:00
switch_channel_set_flag ( tech_pvt - > channel , CF_VIDEO_BREAK ) ;
switch_core_session_kill_channel ( tech_pvt - > session , SWITCH_SIG_BREAK ) ;
2018-01-12 00:40:50 -06:00
goto end ;
2014-06-11 12:48:46 -05:00
}
if ( switch_channel_direction ( tech_pvt - > channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
if ( ( status = verto_connect ( tech_pvt - > session , " verto.invite " ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
2014-12-03 10:16:22 +01:00
} else {
switch_channel_mark_ring_ready ( tech_pvt - > channel ) ;
2014-06-11 12:48:46 -05:00
}
}
2018-01-12 00:40:50 -06:00
end :
if ( status = = SWITCH_STATUS_SUCCESS ) {
track_pvt ( tech_pvt ) ;
}
2014-06-11 12:48:46 -05:00
return status ;
}
static switch_state_handler_table_t verto_state_handlers = {
/*.on_init */ verto_on_init ,
/*.on_routing */ NULL ,
/*.on_execute */ NULL ,
/*.on_hangup */ verto_on_hangup ,
/*.on_exchange_media */ NULL ,
/*.on_soft_execute */ NULL ,
/*.on_consume_media */ NULL ,
/*.on_hibernate */ NULL ,
/*.on_reset */ NULL ,
/*.on_park */ NULL ,
/*.on_reporting */ NULL ,
2015-09-23 10:35:45 -05:00
/*.on_destroy */ verto_on_destroy ,
2014-06-11 12:48:46 -05:00
SSH_FLAG_STICKY
} ;
2018-01-12 00:40:50 -06:00
static switch_status_t verto_set_media_options ( verto_pvt_t * tech_pvt , verto_profile_t * profile )
2014-06-11 12:48:46 -05:00
{
2014-10-18 09:53:57 +02:00
uint32_t i ;
2014-06-11 12:48:46 -05:00
2018-01-12 00:40:50 -06:00
switch_mutex_lock ( profile - > mutex ) ;
2015-05-28 18:02:21 -05:00
if ( ! zstr ( profile - > rtpip [ profile - > rtpip_cur ] ) ) {
tech_pvt - > mparams - > rtpip4 = switch_core_session_strdup ( tech_pvt - > session , profile - > rtpip [ profile - > rtpip_cur + + ] ) ;
tech_pvt - > mparams - > rtpip = tech_pvt - > mparams - > rtpip4 ;
if ( profile - > rtpip_cur = = profile - > rtpip_index ) {
profile - > rtpip_cur = 0 ;
}
}
2014-06-11 12:48:46 -05:00
2015-05-28 18:02:21 -05:00
if ( ! zstr ( profile - > rtpip6 [ profile - > rtpip_cur6 ] ) ) {
tech_pvt - > mparams - > rtpip6 = switch_core_session_strdup ( tech_pvt - > session , profile - > rtpip6 [ profile - > rtpip_cur6 + + ] ) ;
if ( zstr ( tech_pvt - > mparams - > rtpip ) ) {
tech_pvt - > mparams - > rtpip = tech_pvt - > mparams - > rtpip6 ;
}
2017-01-06 02:10:15 -05:00
2015-05-28 18:02:21 -05:00
if ( profile - > rtpip_cur6 = = profile - > rtpip_index6 ) {
profile - > rtpip_cur6 = 0 ;
}
}
2018-01-12 00:40:50 -06:00
switch_mutex_unlock ( profile - > mutex ) ;
2015-05-28 18:02:21 -05:00
if ( zstr ( tech_pvt - > mparams - > rtpip ) ) {
2017-01-06 02:10:15 -05:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( tech_pvt - > session ) , SWITCH_LOG_ERROR , " %s has no media ip, check your configuration \n " ,
2015-05-28 18:02:21 -05:00
switch_channel_get_name ( tech_pvt - > channel ) ) ;
2018-01-12 00:40:50 -06:00
//switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL);
return SWITCH_STATUS_FALSE ;
2014-06-11 12:48:46 -05:00
}
2015-01-23 20:53:00 +00:00
tech_pvt - > mparams - > extrtpip = tech_pvt - > mparams - > extsipip = profile - > extrtpip ;
2014-06-11 12:48:46 -05:00
//tech_pvt->mparams->dtmf_type = tech_pvt->profile->dtmf_type;
switch_channel_set_flag ( tech_pvt - > channel , CF_TRACKABLE ) ;
switch_channel_set_variable ( tech_pvt - > channel , " secondary_recovery_module " , modname ) ;
switch_core_media_check_dtmf_type ( tech_pvt - > session ) ;
//switch_channel_set_cap(tech_pvt->channel, CC_MEDIA_ACK);
switch_channel_set_cap ( tech_pvt - > channel , CC_BYPASS_MEDIA ) ;
//switch_channel_set_cap(tech_pvt->channel, CC_PROXY_MEDIA);
switch_channel_set_cap ( tech_pvt - > channel , CC_JITTERBUFFER ) ;
switch_channel_set_cap ( tech_pvt - > channel , CC_FS_RTP ) ;
//switch_channel_set_cap(tech_pvt->channel, CC_QUEUEABLE_DTMF_DELAY);
//tech_pvt->mparams->ndlb = tech_pvt->profile->mndlb;
tech_pvt - > mparams - > inbound_codec_string = switch_core_session_strdup ( tech_pvt - > session , profile - > inbound_codec_string ) ;
tech_pvt - > mparams - > outbound_codec_string = switch_core_session_strdup ( tech_pvt - > session , profile - > outbound_codec_string ) ;
2017-01-06 02:10:15 -05:00
2019-04-03 05:08:48 -07:00
tech_pvt - > mparams - > jb_msec = profile - > jb_msec ;
2014-06-11 12:48:46 -05:00
switch_media_handle_set_media_flag ( tech_pvt - > smh , SCMF_SUPPRESS_CNG ) ;
//tech_pvt->mparams->auto_rtp_bugs = profile->auto_rtp_bugs;
tech_pvt - > mparams - > timer_name = profile - > timer_name ;
//tech_pvt->mparams->vflags = profile->vflags;
//tech_pvt->mparams->manual_rtp_bugs = profile->manual_rtp_bugs;
//tech_pvt->mparams->manual_video_rtp_bugs = profile->manual_video_rtp_bugs;
tech_pvt - > mparams - > local_network = switch_core_session_strdup ( tech_pvt - > session , profile - > local_network ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
//tech_pvt->mparams->rtcp_audio_interval_msec = profile->rtpp_audio_interval_msec;
//tech_pvt->mparams->rtcp_video_interval_msec = profile->rtpp_video_interval_msec;
//tech_pvt->mparams->sdp_username = profile->sdp_username;
//tech_pvt->mparams->cng_pt = tech_pvt->cng_pt;
//tech_pvt->mparams->rtc_timeout_sec = profile->rtp_timeout_sec;
//tech_pvt->mparams->rtc_hold_timeout_sec = profile->rtp_hold_timeout_sec;
//switch_media_handle_set_media_flags(tech_pvt->media_handle, tech_pvt->profile->media_flags);
for ( i = 0 ; i < profile - > cand_acl_count ; i + + ) {
switch_core_media_add_ice_acl ( tech_pvt - > session , SWITCH_MEDIA_TYPE_AUDIO , profile - > cand_acl [ i ] ) ;
switch_core_media_add_ice_acl ( tech_pvt - > session , SWITCH_MEDIA_TYPE_VIDEO , profile - > cand_acl [ i ] ) ;
}
2017-03-09 13:40:33 -06:00
2017-03-13 11:06:28 -05:00
if ( profile - > enable_text & & ! tech_pvt - > text_read_buffer ) {
2017-03-09 13:40:33 -06:00
set_text_funcs ( tech_pvt - > session ) ;
}
2018-01-12 00:40:50 -06:00
return SWITCH_STATUS_SUCCESS ;
2014-06-11 12:48:46 -05:00
}
static switch_status_t verto_media ( switch_core_session_t * session )
{
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
switch_core_media_prepare_codecs ( tech_pvt - > session , SWITCH_TRUE ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( tech_pvt - > r_sdp ) {
2023-10-18 20:24:14 +03:00
if ( verto_tech_media ( tech_pvt , tech_pvt - > r_sdp , SDP_OFFER ) ! = SWITCH_STATUS_SUCCESS ) {
2014-06-11 12:48:46 -05:00
switch_channel_set_variable ( tech_pvt - > channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " CODEC NEGOTIATION ERROR " ) ;
return SWITCH_STATUS_FALSE ;
}
}
if ( ( status = switch_core_media_choose_ports ( tech_pvt - > session , SWITCH_TRUE , SWITCH_FALSE ) ) ! = SWITCH_STATUS_SUCCESS ) {
//if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
return status ;
}
2023-10-18 20:24:14 +03:00
switch_core_media_gen_local_sdp ( session , SDP_ANSWER , NULL , 0 , NULL , 0 ) ;
2014-06-11 12:48:46 -05:00
if ( switch_core_media_activate_rtp ( tech_pvt - > session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
if ( tech_pvt - > mparams - > local_sdp_str ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Local SDP %s: \n %s \n " , switch_channel_get_name ( tech_pvt - > channel ) ,
tech_pvt - > mparams - > local_sdp_str ) ;
} else {
status = SWITCH_STATUS_FALSE ;
}
return status ;
}
static switch_status_t verto_send_media_indication ( switch_core_session_t * session , const char * method )
{
switch_status_t status = SWITCH_STATUS_FALSE ;
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
const char * proxy_sdp = NULL ;
if ( switch_test_flag ( tech_pvt , TFLAG_SENT_MEDIA ) ) {
status = SWITCH_STATUS_SUCCESS ;
}
if ( switch_channel_test_flag ( tech_pvt - > channel , CF_PROXY_MODE ) ) {
if ( ( proxy_sdp = switch_channel_get_variable ( tech_pvt - > channel , SWITCH_B_SDP_VARIABLE ) ) ) {
status = SWITCH_STATUS_SUCCESS ;
switch_core_media_set_local_sdp ( session , proxy_sdp , SWITCH_TRUE ) ;
}
}
if ( status = = SWITCH_STATUS_SUCCESS | | ( status = verto_media ( session ) ) = = SWITCH_STATUS_SUCCESS ) {
jsock_t * jsock = NULL ;
if ( ! ( jsock = get_jsock ( tech_pvt - > jsock_uuid ) ) ) {
status = SWITCH_STATUS_FALSE ;
} else {
cJSON * params = NULL ;
cJSON * msg = jrpc_new_req ( method , tech_pvt - > call_id , & params ) ;
2020-04-25 01:35:59 +00:00
2014-06-11 12:48:46 -05:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_SENT_MEDIA ) ) {
cJSON_AddItemToObject ( params , " sdp " , cJSON_CreateString ( tech_pvt - > mparams - > local_sdp_str ) ) ;
}
2020-04-25 01:35:59 +00:00
add_variables ( tech_pvt , params ) ;
2014-06-11 12:48:46 -05:00
switch_set_flag ( tech_pvt , TFLAG_SENT_MEDIA ) ;
2014-07-26 02:24:10 +05:00
if ( jsock_queue_event ( jsock , & msg , SWITCH_TRUE ) ! = SWITCH_STATUS_SUCCESS ) {
2014-07-09 13:30:04 -05:00
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
2014-06-11 12:48:46 -05:00
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
}
}
return status ;
}
static switch_status_t messagehook ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_status_t r = SWITCH_STATUS_SUCCESS ;
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_DISPLAY :
{
const char * name , * number ;
cJSON * jmsg = NULL , * params = NULL ;
jsock_t * jsock = NULL ;
if ( ( jsock = get_jsock ( tech_pvt - > jsock_uuid ) ) ) {
name = msg - > string_array_arg [ 0 ] ;
number = msg - > string_array_arg [ 1 ] ;
if ( name | | number ) {
jmsg = jrpc_new_req ( " verto.display " , tech_pvt - > call_id , & params ) ;
2014-08-19 03:25:24 +05:00
switch_ivr_eavesdrop_update_display ( session , name , number ) ;
switch_channel_set_variable ( tech_pvt - > channel , " last_sent_display_name " , name ) ;
switch_channel_set_variable ( tech_pvt - > channel , " last_sent_display_number " , number ) ;
2014-06-11 12:48:46 -05:00
cJSON_AddItemToObject ( params , " display_name " , cJSON_CreateString ( name ) ) ;
cJSON_AddItemToObject ( params , " display_number " , cJSON_CreateString ( number ) ) ;
2014-08-19 03:25:24 +05:00
set_call_params ( params , tech_pvt ) ;
2014-07-24 02:44:34 -04:00
jsock_queue_event ( jsock , & jmsg , SWITCH_TRUE ) ;
2014-06-11 12:48:46 -05:00
}
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
}
}
break ;
2020-04-10 16:48:24 +00:00
case SWITCH_MESSAGE_INDICATE_PROMPT :
{
const char * type = NULL , * text = NULL , * regex = NULL ;
cJSON * jmsg = NULL , * params = NULL ;
jsock_t * jsock = NULL ;
if ( ( jsock = get_jsock ( tech_pvt - > jsock_uuid ) ) ) {
type = msg - > string_array_arg [ 0 ] ;
text = msg - > string_array_arg [ 1 ] ;
regex = msg - > string_array_arg [ 2 ] ;
if ( type & & ( ! strcasecmp ( type , " dtmf " ) | | ! strcasecmp ( type , " message " ) ) & & text ) {
jmsg = jrpc_new_req ( " verto.prompt " , tech_pvt - > call_id , & params ) ;
cJSON_AddItemToObject ( params , " type " , cJSON_CreateString ( type ) ) ;
cJSON_AddItemToObject ( params , " text " , cJSON_CreateString ( text ) ) ;
if ( regex ) {
cJSON_AddItemToObject ( params , " regex " , cJSON_CreateString ( regex ) ) ;
}
jsock_queue_event ( jsock , & jmsg , SWITCH_TRUE ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Error Parsing Media Params \n " ) ;
r = SWITCH_STATUS_FALSE ;
}
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
}
}
break ;
2020-03-29 20:01:03 -05:00
case SWITCH_MESSAGE_INDICATE_MEDIA_PARAMS :
{
const char * json_text ;
cJSON * jmsg = NULL , * params = NULL , * vparams = NULL ;
jsock_t * jsock = NULL ;
if ( ( jsock = get_jsock ( tech_pvt - > jsock_uuid ) ) ) {
json_text = msg - > string_arg ;
if ( json_text ) {
jmsg = jrpc_new_req ( " verto.mediaParams " , tech_pvt - > call_id , & params ) ;
if ( ( vparams = cJSON_Parse ( ( char * ) json_text ) ) ) {
cJSON_AddItemToObject ( params , " mediaParams " , vparams ) ;
jsock_queue_event ( jsock , & jmsg , SWITCH_TRUE ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Error Parsing Media Params \n " ) ;
r = SWITCH_STATUS_FALSE ;
cJSON_Delete ( jmsg ) ;
}
}
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
}
}
break ;
2015-03-23 19:56:19 -05:00
case SWITCH_MESSAGE_INDICATE_MEDIA_RENEG :
{
jsock_t * jsock = NULL ;
if ( ( jsock = get_jsock ( tech_pvt - > jsock_uuid ) ) ) {
switch_core_session_stop_media ( session ) ;
detach_calls ( jsock ) ;
tech_reattach ( tech_pvt , jsock ) ;
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
}
}
break ;
2014-06-11 12:48:46 -05:00
case SWITCH_MESSAGE_INDICATE_ANSWER :
2019-02-21 23:19:52 +00:00
switch_channel_set_variable ( tech_pvt - > channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " ANSWERED " ) ;
switch_channel_mark_pre_answered ( tech_pvt - > channel ) ;
2014-06-11 12:48:46 -05:00
r = verto_send_media_indication ( session , " verto.answer " ) ;
break ;
case SWITCH_MESSAGE_INDICATE_PROGRESS :
r = verto_send_media_indication ( session , " verto.media " ) ;
2019-02-21 23:19:52 +00:00
switch_channel_set_variable ( tech_pvt - > channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " EARLY MEDIA " ) ;
switch_channel_mark_pre_answered ( tech_pvt - > channel ) ;
2014-06-11 12:48:46 -05:00
break ;
default :
break ;
}
return r ;
}
static int verto_recover_callback ( switch_core_session_t * session )
{
int r = 0 ;
char name [ 512 ] ;
verto_pvt_t * tech_pvt = NULL ;
verto_profile_t * profile = NULL ;
const char * profile_name = NULL , * jsock_uuid_str = NULL ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2020-04-14 19:52:38 +00:00
if ( switch_channel_test_flag ( channel , CF_NO_RECOVER ) ) {
2015-11-18 15:26:26 -06:00
return 0 ;
}
2015-09-23 10:35:45 -05:00
PROTECT_INTERFACE ( verto_endpoint_interface ) ;
2014-06-11 12:48:46 -05:00
profile_name = switch_channel_get_variable ( channel , " verto_profile_name " ) ;
jsock_uuid_str = switch_channel_get_variable ( channel , " jsock_uuid_str " ) ;
if ( ! ( profile_name & & jsock_uuid_str & & ( profile = find_profile ( profile_name ) ) ) ) {
2015-09-23 10:35:45 -05:00
UNPROTECT_INTERFACE ( verto_endpoint_interface ) ;
2014-06-11 12:48:46 -05:00
return 0 ;
}
tech_pvt = switch_core_session_alloc ( session , sizeof ( * tech_pvt ) ) ;
2016-07-10 22:25:14 -05:00
tech_pvt - > pool = switch_core_session_get_pool ( session ) ;
2014-06-11 12:48:46 -05:00
tech_pvt - > session = session ;
tech_pvt - > channel = channel ;
tech_pvt - > jsock_uuid = ( char * ) jsock_uuid_str ;
switch_core_session_set_private_class ( session , tech_pvt , SWITCH_PVT_SECONDARY ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
tech_pvt - > call_id = switch_core_session_strdup ( session , switch_core_session_get_uuid ( session ) ) ;
2017-03-13 11:06:28 -05:00
switch_snprintf ( name , sizeof ( name ) , " verto.rtc/%s " , tech_pvt - > jsock_uuid ) ;
switch_channel_set_name ( channel , name ) ;
2014-06-11 12:48:46 -05:00
if ( ( tech_pvt - > smh = switch_core_session_get_media_handle ( session ) ) ) {
tech_pvt - > mparams = switch_core_media_get_mparams ( tech_pvt - > smh ) ;
2018-01-12 00:40:50 -06:00
if ( verto_set_media_options ( tech_pvt , profile ) ! = SWITCH_STATUS_SUCCESS ) {
UNPROTECT_INTERFACE ( verto_endpoint_interface ) ;
return 0 ;
}
2014-06-11 12:48:46 -05:00
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_channel_add_state_handler ( channel , & verto_state_handlers ) ;
switch_core_event_hook_add_receive_message ( session , messagehook ) ;
2017-01-06 02:10:15 -05:00
2018-01-12 00:40:50 -06:00
//track_pvt(tech_pvt);
2014-06-11 12:48:46 -05:00
//switch_channel_clear_flag(tech_pvt->channel, CF_ANSWERED);
//switch_channel_clear_flag(tech_pvt->channel, CF_EARLY_MEDIA);
switch_thread_rwlock_unlock ( profile - > rwlock ) ;
r + + ;
return r ;
}
static void pass_sdp ( verto_pvt_t * tech_pvt )
{
switch_core_session_t * other_session = NULL ;
switch_channel_t * other_channel = NULL ;
if ( switch_core_session_get_partner ( tech_pvt - > session , & other_session ) = = SWITCH_STATUS_SUCCESS ) {
other_channel = switch_core_session_get_channel ( other_session ) ;
2014-10-01 01:28:10 +05:00
switch_channel_pass_sdp ( tech_pvt - > channel , other_channel , tech_pvt - > r_sdp ) ;
2014-06-11 12:48:46 -05:00
switch_channel_set_flag ( other_channel , CF_PROXY_MODE ) ;
switch_core_session_queue_indication ( other_session , SWITCH_MESSAGE_INDICATE_ANSWER ) ;
switch_core_session_rwunlock ( other_session ) ;
}
}
//// METHODS
# define switch_either(_A, _B) zstr(_A) ? _B : _A
static switch_bool_t verto__answer_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
2017-01-06 02:10:15 -05:00
cJSON * obj = cJSON_CreateObject ( ) ;
2014-06-11 12:48:46 -05:00
switch_core_session_t * session ;
cJSON * dialog = NULL ;
const char * call_id = NULL , * sdp = NULL ;
int err = 0 ;
2014-07-18 22:05:07 +05:00
const char * callee_id_name = NULL , * callee_id_number = NULL ;
2014-06-11 12:48:46 -05:00
* response = obj ;
2017-05-09 10:47:00 -05:00
if ( ! params ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Params data missing " ) ) ;
err = 1 ; goto cleanup ;
}
2014-06-11 12:48:46 -05:00
if ( ! ( dialog = cJSON_GetObjectItem ( params , " dialogParams " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Dialog data missing " ) ) ;
err = 1 ; goto cleanup ;
}
if ( ! ( call_id = cJSON_GetObjectCstr ( dialog , " callID " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CallID missing " ) ) ;
err = 1 ; goto cleanup ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! ( sdp = cJSON_GetObjectCstr ( params , " sdp " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " SDP missing " ) ) ;
err = 1 ; goto cleanup ;
}
2014-07-18 22:05:07 +05:00
callee_id_name = cJSON_GetObjectCstr ( dialog , " callee_id_name " ) ;
callee_id_number = cJSON_GetObjectCstr ( dialog , " callee_id_number " ) ;
2014-06-11 12:48:46 -05:00
if ( ( session = switch_core_session_locate ( call_id ) ) ) {
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
2016-12-20 12:20:41 -06:00
switch_core_session_t * other_session = NULL ;
2014-06-11 12:48:46 -05:00
tech_pvt - > r_sdp = switch_core_session_strdup ( session , sdp ) ;
2017-01-06 02:10:15 -05:00
switch_channel_set_variable ( tech_pvt - > channel , SWITCH_R_SDP_VARIABLE , sdp ) ;
2016-03-30 11:42:43 +02:00
switch_channel_set_variable ( tech_pvt - > channel , " verto_client_address " , jsock - > name ) ;
2014-06-11 12:48:46 -05:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Remote SDP %s: \n %s \n " , switch_channel_get_name ( tech_pvt - > channel ) , sdp ) ;
2023-10-18 20:24:14 +03:00
switch_core_media_set_sdp_codec_string ( session , sdp , SDP_ANSWER ) ;
2014-06-11 12:48:46 -05:00
2021-02-05 21:31:17 +00:00
if ( ! switch_channel_var_true ( switch_core_session_get_channel ( session ) , " verto_skip_set_user " ) ) {
switch_ivr_set_user ( session , jsock - > uid ) ;
}
2016-09-20 14:06:05 -05:00
2016-12-20 12:20:41 -06:00
if ( switch_core_session_get_partner ( tech_pvt - > session , & other_session ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_t * other_channel = switch_core_session_get_channel ( other_session ) ;
switch_channel_set_variable ( other_channel , SWITCH_B_SDP_VARIABLE , sdp ) ;
switch_core_session_rwunlock ( other_session ) ;
}
2014-06-11 12:48:46 -05:00
if ( switch_channel_test_flag ( tech_pvt - > channel , CF_PROXY_MODE ) ) {
pass_sdp ( tech_pvt ) ;
} else {
2023-10-18 20:24:14 +03:00
if ( verto_tech_media ( tech_pvt , tech_pvt - > r_sdp , SDP_ANSWER ) ! = SWITCH_STATUS_SUCCESS ) {
2014-06-11 12:48:46 -05:00
switch_channel_set_variable ( tech_pvt - > channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " CODEC NEGOTIATION ERROR " ) ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CODEC ERROR " ) ) ;
err = 1 ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! err & & switch_core_media_activate_rtp ( tech_pvt - > session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " MEDIA ERROR " ) ) ;
err = 1 ;
}
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! err ) {
2014-07-18 22:05:07 +05:00
if ( callee_id_name ) {
switch_channel_set_profile_var ( tech_pvt - > channel , " callee_id_name " , callee_id_name ) ;
}
if ( callee_id_number ) {
switch_channel_set_profile_var ( tech_pvt - > channel , " callee_id_number " , callee_id_number ) ;
}
2014-06-11 12:48:46 -05:00
switch_channel_mark_answered ( tech_pvt - > channel ) ;
}
switch_core_session_rwunlock ( session ) ;
2017-02-03 10:57:01 -06:00
} else {
err = 1 ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CALL DOES NOT EXIST " ) ) ;
2014-06-11 12:48:46 -05:00
}
cleanup :
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! err ) return SWITCH_TRUE ;
2017-02-03 10:57:01 -06:00
2014-06-11 12:48:46 -05:00
cJSON_AddItemToObject ( obj , " code " , cJSON_CreateNumber ( CODE_SESSION_ERROR ) ) ;
return SWITCH_FALSE ;
}
static switch_bool_t verto__bye_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
2017-07-13 12:51:55 -05:00
cJSON * obj = cJSON_CreateObject ( ) , * causeObj = NULL ;
2014-06-11 12:48:46 -05:00
switch_core_session_t * session ;
cJSON * dialog = NULL ;
const char * call_id = NULL , * cause_str = NULL ;
2017-07-13 12:51:55 -05:00
int err = 0 , got_cause = 0 ;
2014-06-11 12:48:46 -05:00
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
* response = obj ;
2017-05-09 12:22:15 -05:00
if ( ! params ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Params data missing " ) ) ;
err = 1 ; goto cleanup ;
}
2014-06-11 12:48:46 -05:00
if ( ! ( dialog = cJSON_GetObjectItem ( params , " dialogParams " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Dialog data missing " ) ) ;
err = 1 ; goto cleanup ;
}
if ( ! ( call_id = cJSON_GetObjectCstr ( dialog , " callID " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CallID missing " ) ) ;
err = 1 ; goto cleanup ;
}
if ( ( cause_str = cJSON_GetObjectCstr ( params , " cause " ) ) ) {
switch_call_cause_t check = switch_channel_str2cause ( cause_str ) ;
if ( check ! = SWITCH_CAUSE_NONE ) {
cause = check ;
2017-07-13 12:51:55 -05:00
got_cause = 1 ;
}
}
if ( ! got_cause & & ( causeObj = cJSON_GetObjectItem ( params , " causeCode " ) ) ) {
int check = 0 ;
const char * cause_str = NULL ;
if ( ! zstr ( causeObj - > valuestring ) ) {
check = atoi ( causeObj - > valuestring ) ;
} else if ( causeObj - > valueint ) {
check = causeObj - > valueint ;
}
cause_str = switch_channel_cause2str ( ( switch_call_cause_t ) check ) ;
if ( ! zstr ( cause_str ) & & strcasecmp ( cause_str , " unknown " ) ) {
cause = ( switch_call_cause_t ) check ;
2014-06-11 12:48:46 -05:00
}
}
2017-01-06 02:10:15 -05:00
cJSON_AddItemToObject ( obj , " callID " , cJSON_CreateString ( call_id ) ) ;
2014-06-11 12:48:46 -05:00
if ( ( session = switch_core_session_locate ( call_id ) ) ) {
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
tech_pvt - > remote_hangup_cause = cause ;
2016-04-15 16:54:38 -03:00
switch_channel_set_variable ( tech_pvt - > channel , " verto_hangup_disposition " , " recv_bye " ) ;
2014-06-11 12:48:46 -05:00
switch_channel_hangup ( tech_pvt - > channel , cause ) ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CALL ENDED " ) ) ;
cJSON_AddItemToObject ( obj , " causeCode " , cJSON_CreateNumber ( cause ) ) ;
cJSON_AddItemToObject ( obj , " cause " , cJSON_CreateString ( switch_channel_cause2str ( cause ) ) ) ;
switch_core_session_rwunlock ( session ) ;
} else {
2017-02-03 10:57:01 -06:00
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CALL DOES NOT EXIST " ) ) ;
2014-06-11 12:48:46 -05:00
err = 1 ;
}
cleanup :
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! err ) return SWITCH_TRUE ;
2017-02-03 10:57:01 -06:00
2014-06-11 12:48:46 -05:00
cJSON_AddItemToObject ( obj , " code " , cJSON_CreateNumber ( CODE_SESSION_ERROR ) ) ;
return SWITCH_FALSE ;
}
static switch_status_t xfer_hanguphook ( switch_core_session_t * session )
{
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
switch_channel_state_t state = switch_channel_get_state ( channel ) ;
if ( state = = CS_HANGUP ) {
switch_core_session_t * ksession ;
const char * uuid = switch_channel_get_variable ( channel , " att_xfer_kill_uuid " ) ;
if ( uuid & & ( ksession = switch_core_session_force_locate ( uuid ) ) ) {
switch_channel_t * kchannel = switch_core_session_get_channel ( ksession ) ;
switch_channel_clear_flag ( kchannel , CF_XFER_ZOMBIE ) ;
switch_channel_clear_flag ( kchannel , CF_TRANSFER ) ;
if ( switch_channel_up ( kchannel ) ) {
switch_channel_hangup ( kchannel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
}
switch_core_session_rwunlock ( ksession ) ;
}
switch_core_event_hook_remove_state_change ( session , xfer_hanguphook ) ;
}
return SWITCH_STATUS_SUCCESS ;
}
static void mark_transfer_record ( switch_core_session_t * session , const char * br_a , const char * br_b )
{
switch_core_session_t * br_b_session , * br_a_session ;
switch_channel_t * channel ;
const char * uvar1 , * dvar1 , * uvar2 , * dvar2 ;
channel = switch_core_session_get_channel ( session ) ;
uvar1 = " verto_user " ;
dvar1 = " verto_host " ;
if ( ( br_b_session = switch_core_session_locate ( br_b ) ) ) {
switch_channel_t * br_b_channel = switch_core_session_get_channel ( br_b_session ) ;
switch_caller_profile_t * cp = switch_channel_get_caller_profile ( br_b_channel ) ;
if ( switch_channel_direction ( br_b_channel ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
uvar2 = " sip_from_user " ;
dvar2 = " sip_from_host " ;
} else {
uvar2 = " sip_to_user " ;
dvar2 = " sip_to_host " ;
}
cp - > transfer_source = switch_core_sprintf ( cp - > pool ,
" %ld:%s:att_xfer:%s@%s/%s@%s " ,
( long ) switch_epoch_time_now ( NULL ) ,
cp - > uuid_str ,
switch_channel_get_variable ( channel , uvar1 ) ,
switch_channel_get_variable ( channel , dvar1 ) ,
switch_channel_get_variable ( br_b_channel , uvar2 ) ,
switch_channel_get_variable ( br_b_channel , dvar2 ) ) ;
switch_channel_add_variable_var_check ( br_b_channel , SWITCH_TRANSFER_HISTORY_VARIABLE , cp - > transfer_source , SWITCH_FALSE , SWITCH_STACK_PUSH ) ;
switch_channel_set_variable ( br_b_channel , SWITCH_TRANSFER_SOURCE_VARIABLE , cp - > transfer_source ) ;
switch_core_session_rwunlock ( br_b_session ) ;
}
if ( ( br_a_session = switch_core_session_locate ( br_a ) ) ) {
switch_channel_t * br_a_channel = switch_core_session_get_channel ( br_a_session ) ;
switch_caller_profile_t * cp = switch_channel_get_caller_profile ( br_a_channel ) ;
if ( switch_channel_direction ( br_a_channel ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
uvar2 = " sip_from_user " ;
dvar2 = " sip_from_host " ;
} else {
uvar2 = " sip_to_user " ;
dvar2 = " sip_to_host " ;
}
cp - > transfer_source = switch_core_sprintf ( cp - > pool ,
" %ld:%s:att_xfer:%s@%s/%s@%s " ,
( long ) switch_epoch_time_now ( NULL ) ,
cp - > uuid_str ,
switch_channel_get_variable ( channel , uvar1 ) ,
switch_channel_get_variable ( channel , dvar1 ) ,
switch_channel_get_variable ( br_a_channel , uvar2 ) ,
switch_channel_get_variable ( br_a_channel , dvar2 ) ) ;
switch_channel_add_variable_var_check ( br_a_channel , SWITCH_TRANSFER_HISTORY_VARIABLE , cp - > transfer_source , SWITCH_FALSE , SWITCH_STACK_PUSH ) ;
switch_channel_set_variable ( br_a_channel , SWITCH_TRANSFER_SOURCE_VARIABLE , cp - > transfer_source ) ;
switch_core_session_rwunlock ( br_a_session ) ;
}
}
static switch_bool_t attended_transfer ( switch_core_session_t * session , switch_core_session_t * b_session ) {
verto_pvt_t * tech_pvt = NULL , * b_tech_pvt = NULL ;
switch_bool_t result = SWITCH_FALSE ;
const char * br_a = NULL , * br_b = NULL ;
tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
b_tech_pvt = switch_core_session_get_private_class ( b_session , SWITCH_PVT_SECONDARY ) ;
2015-07-22 11:00:54 -05:00
if ( tech_pvt & & b_tech_pvt ) {
switch_channel_set_variable ( tech_pvt - > channel , " refer_uuid " , switch_core_session_get_uuid ( b_tech_pvt - > session ) ) ;
2020-03-12 08:23:40 -07:00
switch_channel_set_variable ( tech_pvt - > channel , " transfer_disposition " , " recv_replace " ) ;
2015-07-22 11:00:54 -05:00
switch_channel_set_variable ( b_tech_pvt - > channel , " transfer_disposition " , " replaced " ) ;
2017-01-06 02:10:15 -05:00
2015-07-22 11:00:54 -05:00
br_a = switch_channel_get_partner_uuid ( tech_pvt - > channel ) ;
br_b = switch_channel_get_partner_uuid ( b_tech_pvt - > channel ) ;
2014-06-11 12:48:46 -05:00
2015-07-22 11:00:54 -05:00
if ( ! switch_ivr_uuid_exists ( br_a ) ) {
br_a = NULL ;
}
2014-06-11 12:48:46 -05:00
2015-07-22 11:00:54 -05:00
if ( ! switch_ivr_uuid_exists ( br_b ) ) {
br_b = NULL ;
}
2014-06-11 12:48:46 -05:00
}
2015-07-22 11:00:54 -05:00
if ( tech_pvt & & b_tech_pvt & & switch_channel_test_flag ( b_tech_pvt - > channel , CF_ORIGINATOR ) ) {
2014-06-11 12:48:46 -05:00
switch_core_session_t * a_session ;
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_NOTICE ,
" Attended Transfer on originating session %s \n " , switch_core_session_get_uuid ( b_session ) ) ;
switch_channel_set_variable_printf ( b_tech_pvt - > channel , " transfer_to " , " satt:%s " , br_a ) ;
switch_channel_set_variable ( b_tech_pvt - > channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " ATTENDED_TRANSFER " ) ;
switch_channel_clear_flag ( b_tech_pvt - > channel , CF_LEG_HOLDING ) ;
switch_channel_set_variable ( b_tech_pvt - > channel , SWITCH_HOLDING_UUID_VARIABLE , br_a ) ;
switch_channel_set_flag ( b_tech_pvt - > channel , CF_XFER_ZOMBIE ) ;
switch_channel_set_flag ( b_tech_pvt - > channel , CF_TRANSFER ) ;
if ( ( a_session = switch_core_session_locate ( br_a ) ) ) {
const char * moh = " local_stream://moh " ;
switch_channel_t * a_channel = switch_core_session_get_channel ( a_session ) ;
switch_caller_profile_t * prof = switch_channel_get_caller_profile ( b_tech_pvt - > channel ) ;
const char * tmp ;
switch_core_event_hook_add_state_change ( a_session , xfer_hanguphook ) ;
switch_channel_set_variable ( a_channel , " att_xfer_kill_uuid " , switch_core_session_get_uuid ( b_session ) ) ;
switch_channel_set_variable ( a_channel , " att_xfer_destination_number " , prof - > destination_number ) ;
switch_channel_set_variable ( a_channel , " att_xfer_callee_id_name " , prof - > callee_id_name ) ;
switch_channel_set_variable ( a_channel , " att_xfer_callee_id_number " , prof - > callee_id_number ) ;
if ( ( tmp = switch_channel_get_hold_music ( a_channel ) ) ) {
moh = tmp ;
}
if ( ! zstr ( moh ) & & ! strcasecmp ( moh , " silence " ) ) {
moh = NULL ;
}
if ( moh ) {
char * xdest ;
2016-12-28 12:39:58 -06:00
xdest = switch_core_session_sprintf ( a_session , " m: \" :endless_playback:%s \" park " , moh ) ;
2014-06-11 12:48:46 -05:00
switch_ivr_session_transfer ( a_session , xdest , " inline " , NULL ) ;
} else {
switch_ivr_session_transfer ( a_session , " park " , " inline " , NULL ) ;
}
switch_core_session_rwunlock ( a_session ) ;
result = SWITCH_TRUE ;
2014-06-11 17:11:47 -05:00
switch_channel_hangup ( b_tech_pvt - > channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
2014-06-11 12:48:46 -05:00
} else {
result = SWITCH_FALSE ;
}
} else if ( br_a & & br_b ) {
switch_core_session_t * tmp = NULL ;
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_NOTICE , " Attended Transfer [%s][%s] \n " ,
switch_str_nil ( br_a ) , switch_str_nil ( br_b ) ) ;
if ( ( tmp = switch_core_session_locate ( br_b ) ) ) {
switch_channel_t * tchannel = switch_core_session_get_channel ( tmp ) ;
switch_channel_set_variable ( tchannel , " transfer_disposition " , " bridge " ) ;
switch_channel_set_flag ( tchannel , CF_ATTENDED_TRANSFER ) ;
switch_core_session_rwunlock ( tmp ) ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( switch_true ( switch_channel_get_variable ( tech_pvt - > channel , " recording_follow_transfer " ) ) & &
( tmp = switch_core_session_locate ( br_a ) ) ) {
switch_channel_set_variable ( switch_core_session_get_channel ( tmp ) , " transfer_disposition " , " bridge " ) ;
2018-03-20 09:20:37 +01:00
switch_ivr_transfer_recordings ( session , tmp ) ;
2014-06-11 12:48:46 -05:00
switch_core_session_rwunlock ( tmp ) ;
}
if ( switch_true ( switch_channel_get_variable ( b_tech_pvt - > channel , " recording_follow_transfer " ) ) & &
( tmp = switch_core_session_locate ( br_b ) ) ) {
2018-03-20 09:20:37 +01:00
switch_ivr_transfer_recordings ( b_session , tmp ) ;
2014-06-11 12:48:46 -05:00
switch_core_session_rwunlock ( tmp ) ;
}
switch_channel_set_variable_printf ( tech_pvt - > channel , " transfer_to " , " att:%s " , br_b ) ;
mark_transfer_record ( session , br_a , br_b ) ;
switch_ivr_uuid_bridge ( br_a , br_b ) ;
switch_channel_set_variable ( b_tech_pvt - > channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " ATTENDED_TRANSFER " ) ;
result = SWITCH_TRUE ;
switch_channel_clear_flag ( b_tech_pvt - > channel , CF_LEG_HOLDING ) ;
switch_channel_set_variable ( b_tech_pvt - > channel , " park_timeout " , " 2:attended_transfer " ) ;
switch_channel_set_state ( b_tech_pvt - > channel , CS_PARK ) ;
} else {
if ( ! br_a & & ! br_b ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING ,
" Cannot transfer channels that are not in a bridge. \n " ) ;
result = SWITCH_FALSE ;
} else {
switch_core_session_t * t_session , * hup_session ;
switch_channel_t * hup_channel ;
const char * ext ;
if ( br_a & & ! br_b ) {
t_session = switch_core_session_locate ( br_a ) ;
hup_channel = b_tech_pvt - > channel ;
hup_session = b_session ;
} else {
verto_pvt_t * h_tech_pvt = ( verto_pvt_t * ) switch_core_session_get_private_class ( b_session , SWITCH_PVT_SECONDARY ) ;
t_session = switch_core_session_locate ( br_b ) ;
hup_channel = tech_pvt - > channel ;
hup_session = session ;
switch_channel_clear_flag ( h_tech_pvt - > channel , CF_LEG_HOLDING ) ;
switch_channel_hangup ( b_tech_pvt - > channel , SWITCH_CAUSE_ATTENDED_TRANSFER ) ;
}
if ( t_session ) {
//switch_channel_t *t_channel = switch_core_session_get_channel(t_session);
const char * idest = switch_channel_get_variable ( hup_channel , " inline_destination " ) ;
ext = switch_channel_get_variable ( hup_channel , " destination_number " ) ;
if ( switch_true ( switch_channel_get_variable ( hup_channel , " recording_follow_transfer " ) ) ) {
2018-03-20 09:20:37 +01:00
switch_ivr_transfer_recordings ( hup_session , t_session ) ;
2014-06-11 12:48:46 -05:00
}
if ( idest ) {
switch_ivr_session_transfer ( t_session , idest , " inline " , NULL ) ;
} else {
switch_ivr_session_transfer ( t_session , ext , NULL , NULL ) ;
}
result = SWITCH_TRUE ;
switch_channel_hangup ( hup_channel , SWITCH_CAUSE_ATTENDED_TRANSFER ) ;
2017-09-11 14:47:47 -05:00
switch_core_session_rwunlock ( t_session ) ;
2014-06-11 12:48:46 -05:00
} else {
result = SWITCH_FALSE ;
}
}
}
return result ;
}
static switch_bool_t verto__modify_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
2017-01-06 02:10:15 -05:00
cJSON * obj = cJSON_CreateObject ( ) ;
2014-06-11 12:48:46 -05:00
switch_core_session_t * session ;
cJSON * dialog = NULL ;
const char * call_id = NULL , * destination = NULL , * action = NULL ;
2020-03-18 23:58:33 +00:00
int err = 0 , is_reinvite = 0 ;
verto_pvt_t * tech_pvt = NULL ;
2014-06-11 12:48:46 -05:00
* response = obj ;
2017-05-09 12:22:15 -05:00
if ( ! params ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Params data missing " ) ) ;
err = 1 ; goto cleanup ;
}
2014-06-11 12:48:46 -05:00
if ( ! ( dialog = cJSON_GetObjectItem ( params , " dialogParams " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Dialog data missing " ) ) ;
err = 1 ; goto cleanup ;
}
if ( ! ( call_id = cJSON_GetObjectCstr ( dialog , " callID " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CallID missing " ) ) ;
err = 1 ; goto cleanup ;
}
if ( ! ( action = cJSON_GetObjectCstr ( params , " action " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " action missing " ) ) ;
err = 1 ; goto cleanup ;
}
2020-03-18 23:58:33 +00:00
2017-01-06 02:10:15 -05:00
cJSON_AddItemToObject ( obj , " callID " , cJSON_CreateString ( call_id ) ) ;
cJSON_AddItemToObject ( obj , " action " , cJSON_CreateString ( action ) ) ;
2014-06-11 12:48:46 -05:00
if ( ( session = switch_core_session_locate ( call_id ) ) ) {
2020-03-18 23:58:33 +00:00
tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
2020-08-05 01:39:11 +00:00
if ( ! strcasecmp ( action , " videoRefresh " ) ) {
switch_core_media_gen_key_frame ( tech_pvt - > session ) ;
switch_channel_set_flag ( tech_pvt - > channel , CF_VIDEO_REFRESH_REQ ) ;
} else if ( ! strcasecmp ( action , " updateMedia " ) ) {
2020-03-18 23:58:33 +00:00
const char * sdp = NULL ;
2022-01-07 15:36:46 +03:00
uint8_t p = 0 ;
2020-03-18 23:58:33 +00:00
if ( ! switch_channel_test_flag ( tech_pvt - > channel , CF_ANSWERED ) ) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Cannot update a call that has not been answered. " ) ) ;
err = 1 ; goto rwunlock ;
}
is_reinvite = 1 ;
if ( ! ( sdp = cJSON_GetObjectCstr ( params , " sdp " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " SDP missing " ) ) ;
err = 1 ; goto rwunlock ;
}
tech_pvt - > r_sdp = switch_core_session_strdup ( session , sdp ) ;
switch_channel_set_variable ( tech_pvt - > channel , SWITCH_R_SDP_VARIABLE , tech_pvt - > r_sdp ) ;
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " updateMedia: Remote SDP %s: \n %s \n " ,
switch_channel_get_name ( tech_pvt - > channel ) , tech_pvt - > r_sdp ) ;
switch_core_media_clear_ice ( tech_pvt - > session ) ;
switch_channel_set_flag ( tech_pvt - > channel , CF_REINVITE ) ;
//switch_channel_set_flag(tech_pvt->channel, CF_RECOVERING);
2017-01-06 02:10:15 -05:00
2020-03-18 23:58:33 +00:00
//switch_channel_audio_sync(tech_pvt->channel);
//switch_channel_set_flag(tech_pvt->channel, CF_VIDEO_BREAK);
//switch_core_session_kill_channel(tech_pvt->session, SWITCH_SIG_BREAK);
2023-10-18 20:24:14 +03:00
if ( switch_core_media_negotiate_sdp ( tech_pvt - > session , tech_pvt - > r_sdp , & p , SDP_OFFER ) ) {
switch_core_media_gen_local_sdp ( session , SDP_ANSWER , NULL , 0 , NULL , 0 ) ;
2020-03-18 23:58:33 +00:00
if ( switch_core_media_activate_rtp ( tech_pvt - > session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_set_variable ( tech_pvt - > channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " MEDIA ERROR " ) ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " MEDIA ERROR " ) ) ;
err = 1 ; goto rwunlock ;
}
cJSON_AddItemToObject ( obj , " sdp " , cJSON_CreateString ( tech_pvt - > mparams - > local_sdp_str ) ) ;
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " updateMedia: Local SDP %s: \n %s \n " ,
switch_channel_get_name ( tech_pvt - > channel ) , tech_pvt - > mparams - > local_sdp_str ) ;
2020-07-18 01:05:24 +00:00
switch_core_media_gen_key_frame ( tech_pvt - > session ) ;
switch_channel_set_flag ( tech_pvt - > channel , CF_VIDEO_REFRESH_REQ ) ;
2020-07-28 02:40:48 +00:00
switch_channel_set_flag ( tech_pvt - > channel , CF_REATTACHED ) ;
2020-03-18 23:58:33 +00:00
} else {
switch_channel_set_variable ( tech_pvt - > channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " CODEC NEGOTIATION ERROR " ) ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CODEC NEGOTIATION ERROR " ) ) ;
err = 1 ; goto rwunlock ;
}
2020-07-18 01:05:24 +00:00
2020-03-18 23:58:33 +00:00
} else if ( ! strcasecmp ( action , " transfer " ) ) {
2014-06-11 12:48:46 -05:00
switch_core_session_t * other_session = NULL ;
if ( ! ( destination = cJSON_GetObjectCstr ( params , " destination " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " destination missing " ) ) ;
err = 1 ; goto rwunlock ;
}
2017-01-06 02:10:15 -05:00
if ( switch_core_session_get_partner ( tech_pvt - > session , & other_session ) = = SWITCH_STATUS_SUCCESS ) {
2014-06-11 12:48:46 -05:00
switch_ivr_session_transfer ( other_session , destination , NULL , NULL ) ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CALL TRANSFERRED " ) ) ;
2020-03-12 08:23:40 -07:00
switch_channel_set_variable ( tech_pvt - > channel , " transfer_disposition " , " recv_replace " ) ;
2014-06-11 12:48:46 -05:00
switch_core_session_rwunlock ( other_session ) ;
} else {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " call is not bridged " ) ) ;
err = 1 ; goto rwunlock ;
}
} else if ( ! strcasecmp ( action , " replace " ) ) {
const char * replace_call_id ;
switch_core_session_t * b_session = NULL ;
if ( ! ( replace_call_id = cJSON_GetObjectCstr ( params , " replaceCallID " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " replaceCallID missing " ) ) ;
err = 1 ; goto rwunlock ;
}
if ( ( b_session = switch_core_session_locate ( replace_call_id ) ) ) {
2020-08-12 18:08:07 +01:00
err = ( int ) ! attended_transfer ( session , b_session ) ;
2014-06-11 12:48:46 -05:00
if ( err ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " transfer failed " ) ) ;
}
switch_core_session_rwunlock ( b_session ) ;
} else {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " invalid transfer leg " ) ) ;
err = 1 ; goto rwunlock ;
}
} else if ( ! strcasecmp ( action , " hold " ) ) {
switch_core_media_toggle_hold ( session , 1 ) ;
} else if ( ! strcasecmp ( action , " unhold " ) ) {
switch_core_media_toggle_hold ( session , 0 ) ;
} else if ( ! strcasecmp ( action , " toggleHold " ) ) {
switch_core_media_toggle_hold ( session , ! ! ! switch_channel_test_flag ( tech_pvt - > channel , CF_PROTO_HOLD ) ) ;
}
2017-01-06 02:10:15 -05:00
cJSON_AddItemToObject ( obj , " holdState " , cJSON_CreateString ( switch_channel_test_flag ( tech_pvt - > channel , CF_PROTO_HOLD ) ? " held " : " active " ) ) ;
2014-06-11 12:48:46 -05:00
rwunlock :
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_core_session_rwunlock ( session ) ;
} else {
2017-02-03 10:57:01 -06:00
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CALL DOES NOT EXIST " ) ) ;
2014-06-11 12:48:46 -05:00
err = 1 ;
}
cleanup :
2020-03-18 23:58:33 +00:00
if ( tech_pvt & & is_reinvite ) {
switch_channel_clear_flag ( tech_pvt - > channel , CF_REINVITE ) ;
//switch_channel_clear_flag(tech_pvt->channel, CF_RECOVERING);
switch_clear_flag ( tech_pvt , TFLAG_ATTACH_REQ ) ;
2020-04-23 21:25:21 +00:00
//if (switch_channel_test_flag(tech_pvt->channel, CF_CONFERENCE)) {
// switch_channel_set_flag(tech_pvt->channel, CF_CONFERENCE_ADV);
//}
2020-03-18 23:58:33 +00:00
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! err ) return SWITCH_TRUE ;
2017-02-03 10:57:01 -06:00
2014-06-11 12:48:46 -05:00
cJSON_AddItemToObject ( obj , " code " , cJSON_CreateNumber ( CODE_SESSION_ERROR ) ) ;
return SWITCH_FALSE ;
}
static switch_bool_t verto__attach_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
cJSON * obj = cJSON_CreateObject ( ) ;
switch_core_session_t * session = NULL ;
int err = 0 ;
cJSON * dialog ;
verto_pvt_t * tech_pvt = NULL ;
const char * call_id = NULL , * sdp = NULL ;
2022-01-07 15:36:46 +03:00
uint8_t p = 0 ;
2014-06-11 12:48:46 -05:00
* response = obj ;
2017-05-09 12:22:15 -05:00
if ( ! params ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Params data missing " ) ) ;
err = 1 ; goto cleanup ;
}
2014-06-11 12:48:46 -05:00
if ( ! ( dialog = cJSON_GetObjectItem ( params , " dialogParams " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Dialog data missing " ) ) ;
err = 1 ; goto cleanup ;
}
if ( ! ( sdp = cJSON_GetObjectCstr ( params , " sdp " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " SDP missing " ) ) ;
err = 1 ; goto cleanup ;
}
if ( ! ( call_id = cJSON_GetObjectCstr ( dialog , " callID " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CallID missing " ) ) ;
err = 1 ; goto cleanup ;
}
if ( ! ( session = switch_core_session_locate ( call_id ) ) ) {
2017-02-03 10:57:01 -06:00
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CALL DOES NOT EXIST " ) ) ;
2014-06-11 12:48:46 -05:00
err = 1 ; goto cleanup ;
}
tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
tech_pvt - > r_sdp = switch_core_session_strdup ( session , sdp ) ;
2014-07-29 22:16:56 +05:00
if ( ! switch_channel_test_flag ( tech_pvt - > channel , CF_ANSWERED ) ) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Cannot attach to a call that has not been answered. " ) ) ;
err = 1 ; goto cleanup ;
}
2014-06-11 12:48:46 -05:00
switch_channel_set_variable ( tech_pvt - > channel , SWITCH_R_SDP_VARIABLE , tech_pvt - > r_sdp ) ;
2017-01-06 02:10:15 -05:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Remote SDP %s: \n %s \n " ,
2014-06-11 12:48:46 -05:00
switch_channel_get_name ( tech_pvt - > channel ) , tech_pvt - > r_sdp ) ;
2014-06-13 06:06:14 -04:00
switch_core_media_clear_ice ( tech_pvt - > session ) ;
2014-06-11 12:48:46 -05:00
switch_channel_set_flag ( tech_pvt - > channel , CF_REINVITE ) ;
2020-04-18 02:13:19 +00:00
switch_channel_set_flag ( tech_pvt - > channel , CF_RECOVERING ) ;
2014-06-11 12:48:46 -05:00
2014-06-14 07:05:00 +05:00
//switch_channel_audio_sync(tech_pvt->channel);
//switch_channel_set_flag(tech_pvt->channel, CF_VIDEO_BREAK);
//switch_core_session_kill_channel(tech_pvt->session, SWITCH_SIG_BREAK);
2023-10-18 20:24:14 +03:00
if ( switch_core_media_negotiate_sdp ( tech_pvt - > session , tech_pvt - > r_sdp , & p , SDP_ANSWER ) ) {
//switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
2020-03-18 23:58:33 +00:00
2014-06-11 12:48:46 -05:00
if ( switch_core_media_activate_rtp ( tech_pvt - > session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_set_variable ( tech_pvt - > channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " MEDIA ERROR " ) ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " MEDIA ERROR " ) ) ;
err = 1 ; goto cleanup ;
}
2020-04-18 02:13:19 +00:00
//cJSON_AddItemToObject(obj, "sdp", cJSON_CreateString(tech_pvt->mparams->local_sdp_str));
2020-03-18 23:58:33 +00:00
2014-06-11 12:48:46 -05:00
} else {
switch_channel_set_variable ( tech_pvt - > channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " CODEC NEGOTIATION ERROR " ) ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CODEC NEGOTIATION ERROR " ) ) ;
err = 1 ; goto cleanup ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
cleanup :
if ( tech_pvt ) {
switch_channel_clear_flag ( tech_pvt - > channel , CF_REINVITE ) ;
2020-03-18 23:58:33 +00:00
//switch_channel_clear_flag(tech_pvt->channel, CF_RECOVERING);
2014-06-11 12:48:46 -05:00
switch_clear_flag ( tech_pvt , TFLAG_ATTACH_REQ ) ;
if ( switch_channel_test_flag ( tech_pvt - > channel , CF_CONFERENCE ) ) {
switch_channel_set_flag ( tech_pvt - > channel , CF_CONFERENCE_ADV ) ;
}
}
2020-04-10 21:36:37 +00:00
if ( tech_pvt ) {
if ( err ) {
if ( tech_pvt - > channel ) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL ) ;
}
} else {
switch_core_media_gen_key_frame ( tech_pvt - > session ) ;
switch_channel_set_flag ( tech_pvt - > channel , CF_VIDEO_REFRESH_REQ ) ;
2020-07-28 02:40:48 +00:00
switch_channel_set_flag ( tech_pvt - > channel , CF_REATTACHED ) ;
2020-04-10 21:36:37 +00:00
}
}
2014-06-11 12:48:46 -05:00
if ( session ) {
switch_core_session_rwunlock ( session ) ;
}
if ( ! err ) {
2020-05-22 00:37:09 +00:00
const char * cid_name , * cid_num ;
switch_core_session_message_t msg = { 0 } ;
cid_name = switch_channel_get_variable ( tech_pvt - > channel , " last_sent_display_name " ) ;
cid_num = switch_channel_get_variable ( tech_pvt - > channel , " last_sent_display_number " ) ;
msg . from = __FILE__ ;
msg . string_array_arg [ 0 ] = cid_name ;
msg . string_array_arg [ 1 ] = cid_num ;
msg . message_id = SWITCH_MESSAGE_INDICATE_DISPLAY ;
switch_core_session_receive_message ( session , & msg ) ;
2014-06-11 12:48:46 -05:00
return SWITCH_TRUE ;
}
cJSON_AddItemToObject ( obj , " code " , cJSON_CreateNumber ( CODE_SESSION_ERROR ) ) ;
2017-01-06 02:10:15 -05:00
return SWITCH_FALSE ;
2014-06-11 12:48:46 -05:00
}
2020-12-07 23:09:52 +00:00
2016-09-20 13:57:34 -05:00
static void parse_user_vars ( cJSON * obj , switch_core_session_t * session )
{
2020-12-07 23:09:52 +00:00
cJSON * json_ptr , * var ;
switch_channel_t * channel ;
2016-09-20 13:57:34 -05:00
switch_assert ( obj ) ;
switch_assert ( session ) ;
2020-12-07 23:09:52 +00:00
channel = switch_core_session_get_channel ( session ) ;
if ( ( json_ptr = cJSON_GetObjectItem ( obj , " audio " ) ) ) {
if ( ( var = cJSON_GetObjectItem ( json_ptr , " echoCancellation " ) ) & & var - > type = = cJSON_True ) {
switch_channel_set_variable ( channel , " verto_echoCancellation " , " true " ) ;
} else {
switch_channel_set_variable ( channel , " verto_echoCancellation " , " false " ) ;
}
if ( ( var = cJSON_GetObjectItem ( json_ptr , " noiseSuppression " ) ) & & var - > type = = cJSON_True ) {
switch_channel_set_variable ( channel , " verto_noiseSuppression " , " true " ) ;
} else {
switch_channel_set_variable ( channel , " verto_noiseSuppression " , " false " ) ;
}
if ( ( var = cJSON_GetObjectItem ( json_ptr , " autoGainControl " ) ) & & var - > type = = cJSON_True ) {
switch_channel_set_variable ( channel , " verto_autoGainControl " , " true " ) ;
} else {
switch_channel_set_variable ( channel , " verto_autoGainControl " , " false " ) ;
}
}
2016-09-20 13:57:34 -05:00
if ( ( json_ptr = cJSON_GetObjectItem ( obj , " userVariables " ) ) ) {
cJSON * i ;
for ( i = json_ptr - > child ; i ; i = i - > next ) {
char * varname = switch_core_session_sprintf ( session , " verto_dvar_%s " , i - > string ) ;
if ( i - > type = = cJSON_True ) {
switch_channel_set_variable ( channel , varname , " true " ) ;
} else if ( i - > type = = cJSON_False ) {
switch_channel_set_variable ( channel , varname , " false " ) ;
} else if ( ! zstr ( i - > string ) & & ! zstr ( i - > valuestring ) ) {
switch_channel_set_variable ( channel , varname , i - > valuestring ) ;
}
}
}
}
2020-05-10 21:32:13 +00:00
static switch_bool_t verto__ping_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
* response = cJSON_CreateObject ( ) ;
2021-03-31 20:13:38 +00:00
if ( jsock - > exptime ) {
cJSON_AddItemToObject ( * response , " auth-expires " , cJSON_CreateNumber ( jsock - > exptime ) ) ;
}
2020-05-10 21:32:13 +00:00
cJSON_AddItemToObject ( * response , " message " , cJSON_CreateString ( " PONG " ) ) ;
return SWITCH_TRUE ;
}
2014-06-11 12:48:46 -05:00
static switch_bool_t verto__info_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
2020-02-21 18:52:35 +00:00
cJSON * msg = NULL , * dialog = NULL , * txt = NULL , * jevent = NULL ;
2020-06-23 05:52:14 +00:00
const char * call_id = NULL , * dtmf = NULL , * type = NULL ;
2014-06-11 12:48:46 -05:00
switch_bool_t r = SWITCH_TRUE ;
char * proto = VERTO_CHAT_PROTO ;
char * pproto = NULL ;
2017-05-09 12:22:15 -05:00
int err = 0 ;
2014-06-11 12:48:46 -05:00
* response = cJSON_CreateObject ( ) ;
2017-01-06 02:10:15 -05:00
2017-05-09 12:22:15 -05:00
if ( ! params ) {
cJSON_AddItemToObject ( * response , " message " , cJSON_CreateString ( " Params data missing " ) ) ;
err = 1 ; goto cleanup ;
}
2020-06-23 05:52:14 +00:00
type = cJSON_GetObjectCstr ( params , " type " ) ;
2014-06-11 12:48:46 -05:00
if ( ( dialog = cJSON_GetObjectItem ( params , " dialogParams " ) ) & & ( call_id = cJSON_GetObjectCstr ( dialog , " callID " ) ) ) {
switch_core_session_t * session = NULL ;
2020-06-23 05:52:14 +00:00
switch_channel_t * channel = NULL ;
2014-06-11 12:48:46 -05:00
if ( ( session = switch_core_session_locate ( call_id ) ) ) {
2020-02-21 18:52:35 +00:00
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
if ( ! tech_pvt ) {
cJSON_AddItemToObject ( * response , " message " , cJSON_CreateString ( " Invalid channel " ) ) ;
switch_core_session_rwunlock ( session ) ;
err = 1 ; goto cleanup ;
}
2014-06-11 12:48:46 -05:00
2020-06-23 05:52:14 +00:00
channel = switch_core_session_get_channel ( session ) ;
2016-09-20 13:57:34 -05:00
parse_user_vars ( dialog , session ) ;
2020-06-23 05:52:14 +00:00
if ( type & & ! strcasecmp ( type , " mediaSettings " ) ) {
switch_channel_set_flag ( channel , CF_DEVICES_CHANGED ) ;
}
2020-02-21 18:52:35 +00:00
if ( ( jevent = cJSON_GetObjectItem ( params , " command " ) ) ) {
switch_event_t * event = NULL ;
if ( switch_event_create ( & event , SWITCH_EVENT_COMMAND ) = = SWITCH_STATUS_SUCCESS ) {
char * json_text ;
json_text = cJSON_PrintUnformatted ( jevent ) ;
switch_assert ( json_text ) ;
2017-08-24 11:17:11 -05:00
2020-02-21 18:52:35 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " content-type " , " text/json " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " content-source " , " verto " ) ;
switch_event_add_body ( event , " %s " , json_text ) ;
switch_safe_free ( json_text ) ;
if ( switch_core_session_queue_event ( session , & event ) ! = SWITCH_STATUS_SUCCESS ) {
switch_event_destroy ( & event ) ;
cJSON_AddItemToObject ( * response , " message " , cJSON_CreateString ( " Unexpected Error " ) ) ;
switch_core_session_rwunlock ( session ) ;
err = 1 ; goto cleanup ;
}
2017-08-24 11:17:11 -05:00
}
2020-02-21 18:52:35 +00:00
}
if ( ( dtmf = cJSON_GetObjectCstr ( params , " dtmf " ) ) ) {
char * send ;
2017-08-24 11:17:11 -05:00
send = switch_mprintf ( " ~%s " , dtmf ) ;
2014-10-29 13:14:55 -05:00
if ( switch_channel_test_flag ( tech_pvt - > channel , CF_PROXY_MODE ) ) {
switch_core_session_t * other_session = NULL ;
2017-01-06 02:10:15 -05:00
2014-10-29 13:14:55 -05:00
if ( switch_core_session_get_partner ( tech_pvt - > session , & other_session ) = = SWITCH_STATUS_SUCCESS ) {
switch_core_session_send_dtmf_string ( other_session , send ) ;
switch_core_session_rwunlock ( other_session ) ;
}
} else {
switch_channel_queue_dtmf_string ( tech_pvt - > channel , send ) ;
}
2014-06-11 12:48:46 -05:00
free ( send ) ;
cJSON_AddItemToObject ( * response , " message " , cJSON_CreateString ( " SENT " ) ) ;
}
switch_core_session_rwunlock ( session ) ;
}
}
2017-01-06 02:10:15 -05:00
2016-07-10 22:25:14 -05:00
if ( ( txt = cJSON_GetObjectItem ( params , " txt " ) ) ) {
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( call_id ) ) ) {
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
char charbuf [ 2 ] = " " ;
char * chardata = NULL ;
cJSON * data ;
2017-01-06 02:10:15 -05:00
2017-03-13 11:06:28 -05:00
if ( tech_pvt - > text_read_buffer ) {
if ( ( data = cJSON_GetObjectItem ( txt , " code " ) ) ) {
2016-07-10 22:25:14 -05:00
charbuf [ 0 ] = data - > valueint ;
chardata = charbuf ;
2017-03-13 11:06:28 -05:00
} else if ( ( data = cJSON_GetObjectItem ( txt , " chars " ) ) ) {
if ( data - > valuestring ) {
chardata = data - > valuestring ;
} else if ( data - > valueint ) {
charbuf [ 0 ] = data - > valueint ;
chardata = charbuf ;
}
2016-07-10 22:25:14 -05:00
}
2017-03-13 11:06:28 -05:00
if ( chardata ) {
switch_mutex_lock ( tech_pvt - > text_read_mutex ) ;
switch_buffer_write ( tech_pvt - > text_read_buffer , chardata , strlen ( chardata ) ) ;
switch_mutex_unlock ( tech_pvt - > text_read_mutex ) ;
2017-01-06 02:10:15 -05:00
2017-03-13 11:06:28 -05:00
if ( ( switch_mutex_trylock ( tech_pvt - > text_cond_mutex ) = = SWITCH_STATUS_SUCCESS ) ) {
switch_thread_cond_signal ( tech_pvt - > text_cond ) ;
switch_mutex_unlock ( tech_pvt - > text_cond_mutex ) ;
}
2016-07-10 22:25:14 -05:00
}
2017-03-13 11:06:28 -05:00
2016-07-10 22:25:14 -05:00
}
2017-03-13 11:06:28 -05:00
2016-07-10 22:25:14 -05:00
switch_core_session_rwunlock ( session ) ;
}
}
2014-06-11 12:48:46 -05:00
if ( ( msg = cJSON_GetObjectItem ( params , " msg " ) ) ) {
switch_event_t * event ;
char * to = ( char * ) cJSON_GetObjectCstr ( msg , " to " ) ;
2014-07-24 10:13:32 +05:00
//char *from = (char *) cJSON_GetObjectCstr(msg, "from");
2014-07-24 22:58:12 +05:00
cJSON * i , * indialog = cJSON_GetObjectItem ( msg , " inDialog " ) ;
2014-06-11 12:48:46 -05:00
const char * body = cJSON_GetObjectCstr ( msg , " body " ) ;
2014-07-24 10:13:32 +05:00
switch_bool_t is_dialog = indialog & & ( indialog - > type = = cJSON_True | | ( indialog - > type = = cJSON_String & & switch_true ( indialog - > valuestring ) ) ) ;
2022-02-22 13:11:38 +03:00
const char * context = NULL ;
switch_mutex_lock ( jsock - > flag_mutex ) ;
if ( ! ( context = switch_event_get_header ( jsock - > vars , " user_context " ) ) ) {
context = switch_either ( jsock - > context , jsock - > profile - > context ) ;
}
switch_mutex_unlock ( jsock - > flag_mutex ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! zstr ( to ) ) {
if ( strchr ( to , ' + ' ) ) {
pproto = strdup ( to ) ;
2019-07-12 19:59:40 +04:00
switch_assert ( pproto ) ;
2014-06-11 12:48:46 -05:00
if ( ( to = strchr ( pproto , ' + ' ) ) ) {
* to + + = ' \0 ' ;
}
proto = pproto ;
}
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! zstr ( to ) & & ! zstr ( body ) & & switch_event_create ( & event , SWITCH_EVENT_MESSAGE ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " proto " , VERTO_CHAT_PROTO ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " from " , jsock - > uid ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " from_user " , jsock - > id ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " from_host " , jsock - > domain ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " to " , to ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " type " , " text/plain " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " from_full " , jsock - > id ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " verto_profile " , jsock - > profile - > name ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " verto_jsock_uuid " , jsock - > uuid_str ) ;
2017-01-06 02:10:15 -05:00
2014-07-24 22:58:12 +05:00
for ( i = msg - > child ; i ; i = i - > next ) {
if ( ! zstr ( i - > string ) & & ! zstr ( i - > valuestring ) & & ( ! strncasecmp ( i - > string , " from_ " , 5 ) | | ! strncasecmp ( i - > string , " to_ " , 3 ) ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , i - > string , i - > valuestring ) ;
}
}
2014-07-24 10:13:32 +05:00
if ( is_dialog ) {
2014-06-11 12:48:46 -05:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " call_id " , call_id ) ;
}
2022-02-22 13:11:38 +03:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " context " , context ) ;
2014-06-11 12:48:46 -05:00
switch_event_add_body ( event , " %s " , body ) ;
if ( strcasecmp ( proto , VERTO_CHAT_PROTO ) ) {
switch_core_chat_send ( proto , event ) ;
}
2017-01-06 02:10:15 -05:00
2014-07-24 10:13:32 +05:00
if ( is_dialog ) {
if ( ( dialog = cJSON_GetObjectItem ( params , " dialogParams " ) ) & & ( call_id = cJSON_GetObjectCstr ( dialog , " callID " ) ) ) {
switch_core_session_t * session = NULL ;
2017-01-06 02:10:15 -05:00
2014-07-24 10:13:32 +05:00
if ( ( session = switch_core_session_locate ( call_id ) ) ) {
switch_core_session_queue_event ( session , & event ) ;
switch_core_session_rwunlock ( session ) ;
}
}
} else {
switch_core_chat_send ( " GLOBAL " , event ) ;
}
2017-01-06 02:10:15 -05:00
2014-07-24 10:13:32 +05:00
if ( event ) {
switch_event_destroy ( & event ) ;
}
cJSON_AddItemToObject ( * response , " message " , cJSON_CreateString ( " SENT " ) ) ;
r = SWITCH_TRUE ;
2014-06-11 12:48:46 -05:00
} else {
r = SWITCH_FALSE ;
2017-01-06 02:10:15 -05:00
cJSON_AddItemToObject ( * response , " message " , cJSON_CreateString ( " INVALID MESSAGE to and body params required " ) ) ;
2014-06-11 12:48:46 -05:00
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_safe_free ( pproto ) ;
}
2017-05-09 12:22:15 -05:00
cleanup :
2014-06-11 12:48:46 -05:00
2017-05-09 12:22:15 -05:00
if ( ! err ) return r ;
cJSON_AddItemToObject ( * response , " code " , cJSON_CreateNumber ( CODE_SESSION_ERROR ) ) ;
return SWITCH_FALSE ;
2014-06-11 12:48:46 -05:00
}
2016-07-10 22:25:14 -05:00
2014-06-11 12:48:46 -05:00
static switch_bool_t verto__invite_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
2020-04-14 19:52:38 +00:00
cJSON * obj = cJSON_CreateObject ( ) , * vobj = NULL , * dedEnc = NULL , * mirrorInput , * bandwidth = NULL , * canvas = NULL ;
2014-06-11 12:48:46 -05:00
switch_core_session_t * session = NULL ;
switch_channel_t * channel ;
2023-06-12 17:25:37 +03:00
switch_event_t * var_event = NULL ;
2014-06-11 12:48:46 -05:00
switch_call_cause_t reason = SWITCH_CAUSE_INVALID_MSG_UNSPECIFIED , cancel_cause = 0 ;
switch_caller_profile_t * caller_profile ;
int err = 0 ;
cJSON * dialog ;
verto_pvt_t * tech_pvt ;
char name [ 512 ] ;
2015-11-12 18:33:32 -06:00
const char * var , * destination_number , * call_id = NULL , * sdp = NULL ,
2014-08-04 23:08:29 +05:00
* caller_id_name = NULL , * caller_id_number = NULL , * remote_caller_id_name = NULL , * remote_caller_id_number = NULL , * context = NULL ;
2015-04-25 10:57:09 -05:00
switch_event_header_t * hp ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
* response = obj ;
2019-12-04 22:41:51 +00:00
PROTECT_INTERFACE ( verto_endpoint_interface ) ;
2017-05-09 12:22:15 -05:00
if ( ! params ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Params data missing " ) ) ;
err = 1 ; goto cleanup ;
}
2015-04-16 08:32:52 -07:00
if ( switch_event_create_plain ( & var_event , SWITCH_EVENT_CHANNEL_DATA ) ! = SWITCH_STATUS_SUCCESS ) {
err = 1 ; goto cleanup ;
}
2014-06-11 12:48:46 -05:00
if ( ! ( dialog = cJSON_GetObjectItem ( params , " dialogParams " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Dialog data missing " ) ) ;
err = 1 ; goto cleanup ;
}
if ( ! ( call_id = cJSON_GetObjectCstr ( dialog , " callID " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CallID missing " ) ) ;
err = 1 ; goto cleanup ;
}
if ( ! ( sdp = cJSON_GetObjectCstr ( params , " sdp " ) ) ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " SDP missing " ) ) ;
err = 1 ; goto cleanup ;
}
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , " origination_uuid " , call_id ) ;
2015-09-23 10:35:45 -05:00
2014-06-11 12:48:46 -05:00
if ( ( reason = switch_core_session_outgoing_channel ( NULL , var_event , " rtc " ,
NULL , & session , NULL , SOF_NONE , & cancel_cause ) ) ! = SWITCH_CAUSE_SUCCESS ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Cannot create channel " ) ) ;
err = 1 ; goto cleanup ;
}
channel = switch_core_session_get_channel ( session ) ;
switch_channel_set_direction ( channel , SWITCH_CALL_DIRECTION_INBOUND ) ;
tech_pvt = switch_core_session_alloc ( session , sizeof ( * tech_pvt ) ) ;
tech_pvt - > session = session ;
2016-07-10 22:25:14 -05:00
tech_pvt - > pool = switch_core_session_get_pool ( session ) ;
2014-06-11 12:48:46 -05:00
tech_pvt - > channel = channel ;
tech_pvt - > jsock_uuid = switch_core_session_strdup ( session , jsock - > uuid_str ) ;
tech_pvt - > r_sdp = switch_core_session_strdup ( session , sdp ) ;
2023-10-18 20:24:14 +03:00
switch_core_media_set_sdp_codec_string ( session , sdp , SDP_OFFER ) ;
2014-06-11 12:48:46 -05:00
switch_core_session_set_private_class ( session , tech_pvt , SWITCH_PVT_SECONDARY ) ;
tech_pvt - > call_id = switch_core_session_strdup ( session , call_id ) ;
2017-03-13 11:06:28 -05:00
if ( ! ( destination_number = cJSON_GetObjectCstr ( dialog , " destination_number " ) ) ) {
destination_number = " service " ;
}
switch_snprintf ( name , sizeof ( name ) , " verto.rtc/%s " , destination_number ) ;
switch_channel_set_name ( channel , name ) ;
2014-06-11 12:48:46 -05:00
if ( ( tech_pvt - > smh = switch_core_session_get_media_handle ( session ) ) ) {
tech_pvt - > mparams = switch_core_media_get_mparams ( tech_pvt - > smh ) ;
2018-01-12 00:40:50 -06:00
if ( verto_set_media_options ( tech_pvt , jsock - > profile ) ! = SWITCH_STATUS_SUCCESS ) {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Cannot set media options " ) ) ;
err = 1 ; goto cleanup ;
}
2014-06-11 12:48:46 -05:00
} else {
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " Cannot create media handle " ) ) ;
err = 1 ; goto cleanup ;
}
2020-04-14 19:52:38 +00:00
if ( ( vobj = cJSON_GetObjectItem ( dialog , " screenShare " ) ) & & vobj - > type = = cJSON_True ) {
2015-11-16 15:54:43 -06:00
switch_channel_set_variable ( channel , " video_screen_share " , " true " ) ;
2020-04-14 19:52:38 +00:00
}
if ( ( vobj = cJSON_GetObjectItem ( dialog , " secondSource " ) ) & & vobj - > type = = cJSON_True ) {
switch_channel_set_variable ( channel , " video_second_source " , " true " ) ;
}
if ( ( vobj = cJSON_GetObjectItem ( dialog , " recoverCall " ) ) & & vobj - > type = = cJSON_False ) {
switch_channel_set_flag ( channel , CF_NO_RECOVER ) ;
2015-02-16 21:21:10 -06:00
}
2015-03-05 10:45:57 -06:00
if ( ( dedEnc = cJSON_GetObjectItem ( dialog , " dedEnc " ) ) & & dedEnc - > type = = cJSON_True ) {
switch_channel_set_variable ( channel , " video_use_dedicated_encoder " , " true " ) ;
}
if ( ( mirrorInput = cJSON_GetObjectItem ( dialog , " mirrorInput " ) ) & & mirrorInput - > type = = cJSON_True ) {
switch_channel_set_variable ( channel , " video_mirror_input " , " true " ) ;
switch_channel_set_flag ( channel , CF_VIDEO_MIRROR_INPUT ) ;
}
2016-03-18 14:54:31 -05:00
if ( ( canvas = cJSON_GetObjectItem ( dialog , " conferenceCanvasID " ) ) ) {
int canvas_id = 0 ;
2017-01-06 02:10:15 -05:00
2016-03-18 14:54:31 -05:00
if ( ! zstr ( canvas - > valuestring ) ) {
canvas_id = atoi ( canvas - > valuestring ) ;
} else if ( canvas - > valueint ) {
canvas_id = canvas - > valueint ;
}
if ( canvas_id > = 0 ) {
switch_channel_set_variable_printf ( channel , " video_initial_watching_canvas " , " %d " , canvas_id ) ;
switch_channel_set_variable ( channel , " video_second_screen " , " true " ) ;
}
}
2015-11-12 18:33:32 -06:00
if ( ( bandwidth = cJSON_GetObjectItem ( dialog , " outgoingBandwidth " ) ) ) {
2015-11-18 21:36:41 -06:00
int core_bw = 0 , bwval = 0 ;
const char * val ;
if ( ( val = switch_channel_get_variable_dup ( channel , " rtp_video_max_bandwidth_in " , SWITCH_FALSE , - 1 ) ) ) {
core_bw = switch_parse_bandwidth_string ( val ) ;
}
2015-11-12 18:33:32 -06:00
if ( ! zstr ( bandwidth - > valuestring ) & & strcasecmp ( bandwidth - > valuestring , " default " ) ) {
2015-11-18 21:36:41 -06:00
bwval = atoi ( bandwidth - > valuestring ) ;
2015-11-12 18:33:32 -06:00
} else if ( bandwidth - > valueint ) {
2015-11-18 21:36:41 -06:00
bwval = bandwidth - > valueint ;
}
2017-01-06 02:10:15 -05:00
2016-09-01 17:18:26 -05:00
if ( bwval < 0 ) bwval = 0 ;
2017-01-06 02:10:15 -05:00
2016-09-01 17:18:26 -05:00
if ( core_bw & & bwval & & bwval < core_bw ) {
2015-11-18 21:36:41 -06:00
switch_channel_set_variable_printf ( channel , " rtp_video_max_bandwidth_in " , " %d " , bwval ) ;
2015-02-23 11:13:31 -06:00
}
}
2015-11-12 18:33:32 -06:00
if ( ( bandwidth = cJSON_GetObjectItem ( dialog , " incomingBandwidth " ) ) ) {
2015-11-18 21:36:41 -06:00
int core_bw = 0 , bwval = 0 ;
const char * val ;
if ( ( val = switch_channel_get_variable_dup ( channel , " rtp_video_max_bandwidth_out " , SWITCH_FALSE , - 1 ) ) ) {
core_bw = switch_parse_bandwidth_string ( val ) ;
}
2015-11-12 18:33:32 -06:00
if ( ! zstr ( bandwidth - > valuestring ) & & strcasecmp ( bandwidth - > valuestring , " default " ) ) {
2015-11-18 21:36:41 -06:00
bwval = atoi ( bandwidth - > valuestring ) ;
2015-11-12 18:33:32 -06:00
} else if ( bandwidth - > valueint ) {
2015-11-18 21:36:41 -06:00
bwval = bandwidth - > valueint ;
}
2016-09-01 17:18:26 -05:00
if ( bwval < 0 ) bwval = 0 ;
if ( core_bw & & bwval & & bwval < core_bw ) {
2015-11-18 21:36:41 -06:00
switch_channel_set_variable_printf ( channel , " rtp_video_max_bandwidth_out " , " %d " , bwval ) ;
2015-02-23 11:13:31 -06:00
}
}
2015-02-16 21:21:10 -06:00
2016-09-20 13:57:34 -05:00
parse_user_vars ( dialog , session ) ;
2015-07-02 17:55:04 -05:00
2017-03-13 11:06:28 -05:00
2014-06-11 12:48:46 -05:00
switch_channel_set_variable ( channel , " jsock_uuid_str " , jsock - > uuid_str ) ;
switch_channel_set_variable ( channel , " verto_user " , jsock - > uid ) ;
2014-07-24 10:13:32 +05:00
switch_channel_set_variable ( channel , " presence_id " , jsock - > uid ) ;
2016-03-30 11:42:43 +02:00
switch_channel_set_variable ( channel , " verto_client_address " , jsock - > name ) ;
2014-07-24 10:13:32 +05:00
switch_channel_set_variable ( channel , " chat_proto " , VERTO_CHAT_PROTO ) ;
2014-06-11 12:48:46 -05:00
switch_channel_set_variable ( channel , " verto_host " , jsock - > domain ) ;
switch_channel_set_variable ( channel , " event_channel_cookie " , tech_pvt - > jsock_uuid ) ;
switch_channel_set_variable ( channel , " verto_profile_name " , jsock - > profile - > name ) ;
caller_id_name = cJSON_GetObjectCstr ( dialog , " caller_id_name " ) ;
caller_id_number = cJSON_GetObjectCstr ( dialog , " caller_id_number " ) ;
2014-08-04 23:08:29 +05:00
remote_caller_id_name = cJSON_GetObjectCstr ( dialog , " remote_caller_id_name " ) ;
remote_caller_id_number = cJSON_GetObjectCstr ( dialog , " remote_caller_id_number " ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( zstr ( caller_id_name ) ) {
if ( ( var = switch_event_get_header ( jsock - > params , " caller-id-name " ) ) ) {
caller_id_name = var ;
}
2015-07-23 19:09:24 -05:00
} else if ( caller_id_name ) {
2020-09-26 02:09:34 +00:00
if ( ! switch_event_get_header ( jsock - > params , " caller-id-name " ) ) {
switch_event_add_header_string ( jsock - > params , SWITCH_STACK_BOTTOM , " caller-id-name " , caller_id_name ) ;
}
2014-06-11 12:48:46 -05:00
}
2015-07-23 19:09:24 -05:00
2014-06-11 12:48:46 -05:00
if ( zstr ( caller_id_number ) ) {
if ( ( var = switch_event_get_header ( jsock - > params , " caller-id-number " ) ) ) {
caller_id_number = var ;
}
}
2017-01-06 02:10:15 -05:00
2020-04-13 23:17:37 +00:00
switch_mutex_lock ( jsock - > flag_mutex ) ;
2014-06-11 12:48:46 -05:00
if ( ! ( context = switch_event_get_header ( jsock - > vars , " user_context " ) ) ) {
context = switch_either ( jsock - > context , jsock - > profile - > context ) ;
}
2020-04-13 23:17:37 +00:00
switch_mutex_unlock ( jsock - > flag_mutex ) ;
2014-06-11 12:48:46 -05:00
if ( ( caller_profile = switch_caller_profile_new ( switch_core_session_get_pool ( session ) ,
jsock - > uid ,
switch_either ( jsock - > dialplan , jsock - > profile - > dialplan ) ,
caller_id_name ,
caller_id_number ,
2015-05-28 18:02:21 -05:00
jsock - > remote_host ,
2014-06-11 12:48:46 -05:00
cJSON_GetObjectCstr ( dialog , " ani " ) ,
cJSON_GetObjectCstr ( dialog , " aniii " ) ,
2017-01-06 02:10:15 -05:00
cJSON_GetObjectCstr ( dialog , " rdnis " ) ,
modname ,
2014-06-11 12:48:46 -05:00
context ,
destination_number ) ) ) {
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_channel_set_caller_profile ( channel , caller_profile ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
}
2021-02-05 21:31:17 +00:00
if ( ! switch_channel_var_true ( channel , " verto_skip_set_user " ) ) {
switch_ivr_set_user ( session , jsock - > uid ) ;
}
2015-04-25 10:57:09 -05:00
2021-01-24 19:08:44 +00:00
switch_mutex_lock ( jsock - > flag_mutex ) ;
2015-04-25 10:57:09 -05:00
for ( hp = jsock - > user_vars - > headers ; hp ; hp = hp - > next ) {
switch_channel_set_variable ( channel , hp - > name , hp - > value ) ;
}
2021-01-24 19:08:44 +00:00
switch_mutex_unlock ( jsock - > flag_mutex ) ;
2015-04-25 10:57:09 -05:00
2014-08-04 23:08:29 +05:00
switch_channel_set_profile_var ( channel , " callee_id_name " , remote_caller_id_name ) ;
switch_channel_set_profile_var ( channel , " callee_id_number " , remote_caller_id_number ) ;
switch_channel_set_variable ( channel , " verto_remote_caller_id_name " , remote_caller_id_name ) ;
switch_channel_set_variable ( channel , " verto_remote_caller_id_number " , remote_caller_id_number ) ;
2014-06-11 12:48:46 -05:00
switch_channel_set_variable ( channel , SWITCH_R_SDP_VARIABLE , sdp ) ;
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Remote SDP %s: \n %s \n " , switch_channel_get_name ( tech_pvt - > channel ) , sdp ) ;
2017-01-06 02:10:15 -05:00
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CALL CREATED " ) ) ;
cJSON_AddItemToObject ( obj , " callID " , cJSON_CreateString ( tech_pvt - > call_id ) ) ;
2014-06-11 12:48:46 -05:00
switch_channel_add_state_handler ( channel , & verto_state_handlers ) ;
switch_core_event_hook_add_receive_message ( session , messagehook ) ;
switch_channel_set_state ( channel , CS_INIT ) ;
2018-01-12 00:40:50 -06:00
//track_pvt(tech_pvt);
2014-06-11 12:48:46 -05:00
switch_core_session_thread_launch ( session ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
cleanup :
switch_event_destroy ( & var_event ) ;
if ( ! err ) {
return SWITCH_TRUE ;
}
2015-09-23 10:35:45 -05:00
UNPROTECT_INTERFACE ( verto_endpoint_interface ) ;
2014-06-11 12:48:46 -05:00
if ( session ) {
switch_core_session_destroy ( & session ) ;
}
cJSON_AddItemToObject ( obj , " causeCode " , cJSON_CreateNumber ( reason ) ) ;
cJSON_AddItemToObject ( obj , " cause " , cJSON_CreateString ( switch_channel_cause2str ( reason ) ) ) ;
cJSON_AddItemToObject ( obj , " message " , cJSON_CreateString ( " CALL ERROR " ) ) ;
cJSON_AddItemToObject ( obj , " code " , cJSON_CreateNumber ( CODE_SESSION_ERROR ) ) ;
return SWITCH_FALSE ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
}
static switch_bool_t event_channel_check_auth ( jsock_t * jsock , const char * event_channel )
{
char * main_event_channel = NULL ;
switch_bool_t ok = SWITCH_TRUE , pre_ok = SWITCH_FALSE ;
switch_core_session_t * session = NULL ;
switch_assert ( event_channel ) ;
pre_ok = switch_event_channel_permission_verify ( jsock - > uuid_str , event_channel ) ;
if ( ! pre_ok & & ( session = switch_core_session_locate ( event_channel ) ) ) {
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
const char * jsock_uuid_str = switch_channel_get_variable ( channel , " jsock_uuid_str " ) ;
if ( jsock_uuid_str & & ! strcmp ( jsock_uuid_str , jsock - > uuid_str ) ) {
pre_ok = SWITCH_TRUE ;
}
switch_core_session_rwunlock ( session ) ;
}
if ( pre_ok ) {
return pre_ok ;
}
if ( jsock - > allowed_event_channels ) {
if ( strchr ( event_channel , ' . ' ) ) {
char * p ;
main_event_channel = strdup ( event_channel ) ;
2019-07-12 19:59:40 +04:00
switch_assert ( main_event_channel ) ;
2014-06-11 12:48:46 -05:00
if ( ( p = strchr ( main_event_channel , ' . ' ) ) ) {
* p = ' \0 ' ;
}
}
2017-02-09 17:23:30 -06:00
if ( ( ! verto_globals . enable_fs_events & & ( ! strcasecmp ( event_channel , " FSevent " ) | | ( main_event_channel & & ! strcasecmp ( main_event_channel , " FSevent " ) ) ) ) | |
2014-07-18 01:03:57 +05:00
! ( switch_event_get_header ( jsock - > allowed_event_channels , event_channel ) | |
2014-06-11 12:48:46 -05:00
( main_event_channel & & switch_event_get_header ( jsock - > allowed_event_channels , main_event_channel ) ) ) ) {
ok = SWITCH_FALSE ;
}
}
switch_safe_free ( main_event_channel ) ;
return ok ;
}
static switch_bool_t parse_subs ( jsock_t * jsock , const char * event_channel , cJSON * * sub_list , cJSON * * err_list , cJSON * * exist_list )
{
switch_bool_t r = SWITCH_FALSE ;
if ( event_channel_check_auth ( jsock , event_channel ) ) {
if ( ! * sub_list ) {
2017-01-06 02:10:15 -05:00
* sub_list = cJSON_CreateArray ( ) ;
2014-06-11 12:48:46 -05:00
}
if ( jsock_sub_channel ( jsock , event_channel ) = = SWITCH_STATUS_SUCCESS ) {
cJSON_AddItemToArray ( * sub_list , cJSON_CreateString ( event_channel ) ) ;
} else {
if ( ! * exist_list ) {
2017-01-06 02:10:15 -05:00
* exist_list = cJSON_CreateArray ( ) ;
2014-06-11 12:48:46 -05:00
}
cJSON_AddItemToArray ( * exist_list , cJSON_CreateString ( event_channel ) ) ;
}
r = SWITCH_TRUE ;
} else {
if ( ! * err_list ) {
2017-01-06 02:10:15 -05:00
* err_list = cJSON_CreateArray ( ) ;
2014-06-11 12:48:46 -05:00
}
cJSON_AddItemToArray ( * err_list , cJSON_CreateString ( event_channel ) ) ;
}
return r ;
}
static switch_bool_t verto__subscribe_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
switch_bool_t r = SWITCH_TRUE ;
cJSON * subs = NULL , * errs = NULL , * exist = NULL ;
* response = cJSON_CreateObject ( ) ;
if ( params ) {
cJSON * jchannel = cJSON_GetObjectItem ( params , " eventChannel " ) ;
if ( jchannel ) {
if ( jchannel - > type = = cJSON_String ) {
parse_subs ( jsock , jchannel - > valuestring , & subs , & errs , & exist ) ;
} else if ( jchannel - > type = = cJSON_Array ) {
int i , len = cJSON_GetArraySize ( jchannel ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
for ( i = 0 ; i < len ; i + + ) {
cJSON * str = cJSON_GetArrayItem ( jchannel , i ) ;
if ( str - > type = = cJSON_String ) {
parse_subs ( jsock , str - > valuestring , & subs , & errs , & exist ) ;
}
}
}
}
}
if ( subs ) {
cJSON_AddItemToObject ( * response , " subscribedChannels " , subs ) ;
}
if ( errs ) {
cJSON_AddItemToObject ( * response , " unauthorizedChannels " , errs ) ;
}
if ( exist ) {
cJSON_AddItemToObject ( * response , " alreadySubscribedChannels " , exist ) ;
}
if ( ! subs ) {
r = SWITCH_FALSE ;
}
return r ;
}
2017-01-06 02:10:15 -05:00
static void do_unsub ( jsock_t * jsock , const char * event_channel , cJSON * * subs , cJSON * * errs )
2014-06-11 12:48:46 -05:00
{
if ( jsock_unsub_channel ( jsock , event_channel ) ) {
if ( ! * subs ) {
2017-01-06 02:10:15 -05:00
* subs = cJSON_CreateArray ( ) ;
2014-06-11 12:48:46 -05:00
}
cJSON_AddItemToArray ( * subs , cJSON_CreateString ( event_channel ) ) ;
} else {
if ( ! * errs ) {
2017-01-06 02:10:15 -05:00
* errs = cJSON_CreateArray ( ) ;
2014-06-11 12:48:46 -05:00
}
cJSON_AddItemToArray ( * errs , cJSON_CreateString ( event_channel ) ) ;
}
}
static switch_bool_t verto__unsubscribe_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
switch_bool_t r = SWITCH_TRUE ;
cJSON * subs = NULL , * errs = NULL ;
* response = cJSON_CreateObject ( ) ;
if ( params ) {
cJSON * jchannel = cJSON_GetObjectItem ( params , " eventChannel " ) ;
if ( jchannel ) {
if ( jchannel - > type = = cJSON_String ) {
do_unsub ( jsock , jchannel - > valuestring , & subs , & errs ) ;
} else if ( jchannel - > type = = cJSON_Array ) {
int i , len = cJSON_GetArraySize ( jchannel ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
for ( i = 0 ; i < len ; i + + ) {
cJSON * str = cJSON_GetArrayItem ( jchannel , i ) ;
if ( str - > type = = cJSON_String ) {
do_unsub ( jsock , str - > valuestring , & subs , & errs ) ;
}
}
}
}
}
if ( subs ) {
cJSON_AddItemToObject ( * response , " unsubscribedChannels " , subs ) ;
}
if ( errs ) {
cJSON_AddItemToObject ( * response , " notSubscribedChannels " , errs ) ;
}
if ( errs & & ! subs ) {
r = SWITCH_FALSE ;
}
return r ;
}
static switch_bool_t verto__broadcast_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
char * json_text = NULL ;
const char * event_channel = cJSON_GetObjectCstr ( params , " eventChannel " ) ;
2016-11-02 16:00:49 -05:00
cJSON * jevent , * broadcast ;
2015-07-23 19:09:24 -05:00
const char * display = NULL ;
2014-06-11 12:48:46 -05:00
* response = cJSON_CreateObject ( ) ;
if ( ! event_channel ) {
cJSON_AddItemToObject ( * response , " message " , cJSON_CreateString ( " eventChannel not specified. " ) ) ;
cJSON_AddItemToObject ( * response , " code " , cJSON_CreateNumber ( CODE_SESSION_ERROR ) ) ;
goto end ;
}
if ( ! event_channel_check_auth ( jsock , event_channel ) ) {
cJSON_AddItemToObject ( * response , " message " , cJSON_CreateString ( " Permission Denied. " ) ) ;
cJSON_AddItemToObject ( * response , " code " , cJSON_CreateNumber ( CODE_SESSION_ERROR ) ) ;
goto end ;
}
2017-01-06 02:10:15 -05:00
cJSON_AddItemToObject ( params , " userid " , cJSON_CreateString ( jsock - > uid ) ) ;
2021-03-05 01:46:01 +00:00
cJSON_AddItemToObject ( params , " sessid " , cJSON_CreateString ( jsock - > uuid_str ) ) ;
2014-06-11 12:48:46 -05:00
2015-07-23 19:09:24 -05:00
display = switch_event_get_header ( jsock - > params , " caller-id-name " ) ;
if ( display ) {
cJSON_AddItemToObject ( params , " fromDisplay " , cJSON_CreateString ( display ) ) ;
}
2014-06-11 12:48:46 -05:00
jevent = cJSON_Duplicate ( params , 1 ) ;
2017-01-06 02:10:15 -05:00
2016-11-02 16:00:49 -05:00
broadcast = cJSON_GetObjectItem ( params , " localBroadcast " ) ;
2014-06-11 12:48:46 -05:00
2016-11-02 16:00:49 -05:00
if ( broadcast & & broadcast - > type = = cJSON_True ) {
2020-10-22 19:25:29 +00:00
write_event ( event_channel , NULL , NULL , jevent ) ;
2016-11-02 16:00:49 -05:00
} else {
2017-02-09 17:23:30 -06:00
switch_event_channel_broadcast ( event_channel , & jevent , modname , verto_globals . event_channel_id ) ;
2016-11-02 16:00:49 -05:00
}
2016-08-10 21:57:42 -05:00
2020-03-25 03:49:19 +04:00
if ( jsock - > profile - > mcast_pub . sock ! = KS_SOCK_INVALID ) {
2014-06-11 12:48:46 -05:00
if ( ( json_text = cJSON_PrintUnformatted ( params ) ) ) {
2016-01-28 12:29:45 -06:00
if ( mcast_socket_send ( & jsock - > profile - > mcast_pub , json_text , strlen ( json_text ) + 1 ) < = 0 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " multicast socket send error! %s \n " , strerror ( errno ) ) ;
2016-11-30 18:17:47 -06:00
//r = SWITCH_FALSE;
//cJSON_AddItemToObject(*response, "message", cJSON_CreateString("MCAST Data Send failure!"));
2016-01-28 12:29:45 -06:00
} else {
2016-11-30 18:17:47 -06:00
//r = SWITCH_TRUE;
//cJSON_AddItemToObject(*response, "message", cJSON_CreateString("MCAST Data Sent"));
2019-07-09 23:31:55 -05:00
if ( verto_globals . debug > 0 ) {
2020-04-01 00:31:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , verto_globals . debug_level , " MCAST Data Sent: %s \n " , json_text ) ;
2019-07-09 23:31:55 -05:00
}
2014-06-11 17:11:47 -05:00
}
2014-06-11 12:48:46 -05:00
free ( json_text ) ;
json_text = NULL ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " JSON ERROR! \n " ) ;
}
}
end :
2016-11-30 18:17:47 -06:00
return SWITCH_TRUE ;
2014-06-11 12:48:46 -05:00
}
static switch_bool_t login_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
2020-04-13 23:17:37 +00:00
const char * var ;
2014-06-11 12:48:46 -05:00
* response = cJSON_CreateObject ( ) ;
cJSON_AddItemToObject ( * response , " message " , cJSON_CreateString ( " logged in " ) ) ;
2021-02-03 21:18:07 +00:00
if ( jsock - > exptime ) {
cJSON_AddItemToObject ( * response , " auth-expires " , cJSON_CreateNumber ( jsock - > exptime ) ) ;
}
2020-04-13 23:17:37 +00:00
switch_mutex_lock ( jsock - > flag_mutex ) ;
if ( ( var = switch_event_get_header ( jsock - > vars , " moderator " ) ) & & switch_true ( var ) ) {
cJSON_AddItemToObject ( * response , " moderator " , cJSON_CreateTrue ( ) ) ;
switch_event_add_header_string ( jsock - > vars , SWITCH_STACK_BOTTOM , " conf_mvar_moderator " , " true " ) ;
}
2020-06-03 21:50:29 +00:00
if ( ( var = switch_event_get_header ( jsock - > vars , " stereo_audio " ) ) & & switch_true ( var ) ) {
cJSON_AddItemToObject ( * response , " stereoAudio " , cJSON_CreateTrue ( ) ) ;
}
2020-04-13 23:17:37 +00:00
if ( ( var = switch_event_get_header ( jsock - > vars , " superuser " ) ) & & switch_true ( var ) ) {
switch_event_add_header_string ( jsock - > vars , SWITCH_STACK_BOTTOM , " conf_mvar_superuser " , " true " ) ;
cJSON_AddItemToObject ( * response , " superuser " , cJSON_CreateTrue ( ) ) ;
}
switch_mutex_unlock ( jsock - > flag_mutex ) ;
2014-08-01 23:07:13 +05:00
login_fire_custom_event ( jsock , params , 1 , " Logged in " ) ;
2014-06-11 12:48:46 -05:00
return SWITCH_TRUE ;
}
static switch_bool_t echo_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
2017-05-09 12:22:15 -05:00
if ( params ) {
* response = cJSON_Duplicate ( params , 1 ) ;
return SWITCH_TRUE ;
}
* response = cJSON_CreateObject ( ) ;
cJSON_AddItemToObject ( * response , " message " , cJSON_CreateString ( " Params data missing " ) ) ;
cJSON_AddItemToObject ( * response , " code " , cJSON_CreateNumber ( CODE_SESSION_ERROR ) ) ;
return SWITCH_FALSE ;
2014-06-11 12:48:46 -05:00
}
static switch_bool_t jsapi_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
2020-08-03 17:57:59 +00:00
switch_event_header_t * hi = NULL ;
cJSON * obj ;
const char * var ;
2014-06-11 12:48:46 -05:00
if ( jsock - > allowed_jsapi ) {
const char * function ;
if ( params ) {
if ( ( function = cJSON_GetObjectCstr ( params , " command " ) ) ) {
if ( ! switch_event_get_header ( jsock - > allowed_jsapi , function ) ) {
return SWITCH_FALSE ;
}
if ( jsock - > allowed_fsapi & & ! strcmp ( function , " fsapi " ) ) {
2015-01-03 16:06:35 +08:00
cJSON * data = cJSON_GetObjectItem ( params , " data " ) ;
2015-01-08 11:38:53 +08:00
if ( data ) {
cJSON * cmd = cJSON_GetObjectItem ( data , " cmd " ) ;
cJSON * arg = cJSON_GetObjectItem ( data , " arg " ) ;
if ( cmd & & cmd - > type = = cJSON_String & & cmd - > valuestring & &
! auth_api_command ( jsock , cmd - > valuestring , arg ? arg - > valuestring : NULL ) ) {
return SWITCH_FALSE ;
}
2014-06-11 12:48:46 -05:00
}
}
}
}
}
2020-08-03 17:57:59 +00:00
obj = cJSON_CreateObject ( ) ;
cJSON_AddItemToObject ( obj , " verto_id " , cJSON_CreateString ( ( char * ) jsock - > id ) ) ;
cJSON_AddItemToObject ( obj , " verto_domain " , cJSON_CreateString ( ( char * ) jsock - > domain ) ) ;
cJSON_AddItemToObject ( obj , " verto_user " , cJSON_CreateString ( ( char * ) jsock - > uid ) ) ;
cJSON_AddItemToObject ( obj , " presence_id " , cJSON_CreateString ( ( char * ) jsock - > uid ) ) ;
cJSON_AddItemToObject ( obj , " verto_client_address " , cJSON_CreateString ( ( char * ) jsock - > name ) ) ;
cJSON_AddItemToObject ( obj , " chat_proto " , cJSON_CreateString ( ( char * ) VERTO_CHAT_PROTO ) ) ;
cJSON_AddItemToObject ( obj , " verto_host " , cJSON_CreateString ( ( char * ) jsock - > domain ) ) ;
2021-01-24 19:08:44 +00:00
switch_mutex_lock ( jsock - > flag_mutex ) ;
2020-08-03 17:57:59 +00:00
for ( hi = jsock - > user_vars - > headers ; hi ; hi = hi - > next ) {
cJSON_AddItemToObject ( obj , hi - > name , cJSON_CreateString ( ( char * ) hi - > value ) ) ;
}
2021-01-24 19:08:44 +00:00
switch_mutex_unlock ( jsock - > flag_mutex ) ;
2020-08-03 17:57:59 +00:00
if ( ( var = switch_event_get_header ( jsock - > params , " caller-id-name " ) ) ) {
cJSON_AddItemToObject ( obj , " caller-id-name " , cJSON_CreateString ( ( char * ) var ) ) ;
}
if ( ( var = switch_event_get_header ( jsock - > params , " caller-id-number " ) ) ) {
cJSON_AddItemToObject ( obj , " caller-id-number " , cJSON_CreateString ( ( char * ) var ) ) ;
}
cJSON_AddItemToObject ( params , " sockData " , obj ) ;
2014-06-11 12:48:46 -05:00
switch_json_api_execute ( params , NULL , response ) ;
return * response ? SWITCH_TRUE : SWITCH_FALSE ;
}
static switch_bool_t fsapi_func ( const char * method , cJSON * params , jsock_t * jsock , cJSON * * response )
{
2017-05-09 12:22:15 -05:00
cJSON * cmd = NULL , * arg = NULL , * reply ;
2014-06-11 12:48:46 -05:00
switch_stream_handle_t stream = { 0 } ;
2017-05-09 12:22:15 -05:00
if ( params ) {
cmd = cJSON_GetObjectItem ( params , " cmd " ) ;
arg = cJSON_GetObjectItem ( params , " arg " ) ;
}
2014-06-11 12:48:46 -05:00
2015-01-16 09:47:40 -06:00
if ( cmd & & jsock - > allowed_fsapi ) {
2014-06-11 12:48:46 -05:00
if ( cmd - > type = = cJSON_String & & cmd - > valuestring & & ! auth_api_command ( jsock , cmd - > valuestring , arg ? arg - > valuestring : NULL ) ) {
return SWITCH_FALSE ;
}
}
if ( cmd & & ! cmd - > valuestring ) {
cmd = NULL ;
}
if ( arg & & ! arg - > valuestring ) {
arg = NULL ;
}
reply = cJSON_CreateObject ( ) ;
SWITCH_STANDARD_STREAM ( stream ) ;
2017-01-06 02:10:15 -05:00
2022-01-07 15:36:46 +03:00
if ( cmd & & switch_api_execute ( cmd - > valuestring , arg ? arg - > valuestring : NULL , NULL , & stream ) = = SWITCH_STATUS_SUCCESS ) {
2014-06-11 12:48:46 -05:00
cJSON_AddItemToObject ( reply , " message " , cJSON_CreateString ( ( char * ) stream . data ) ) ;
} else {
cJSON_AddItemToObject ( reply , " message " , cJSON_CreateString ( " INVALID CALL " ) ) ;
}
switch_safe_free ( stream . data ) ;
if ( reply ) {
* response = reply ;
return SWITCH_TRUE ;
}
return SWITCH_FALSE ;
}
////
static void jrpc_init ( void )
{
jrpc_add_func ( " echo " , echo_func ) ;
jrpc_add_func ( " jsapi " , jsapi_func ) ;
jrpc_add_func ( " fsapi " , fsapi_func ) ;
jrpc_add_func ( " login " , login_func ) ;
jrpc_add_func ( " verto.invite " , verto__invite_func ) ;
2020-05-10 21:32:13 +00:00
jrpc_add_func ( " verto.ping " , verto__ping_func ) ;
2014-06-11 12:48:46 -05:00
jrpc_add_func ( " verto.info " , verto__info_func ) ;
jrpc_add_func ( " verto.attach " , verto__attach_func ) ;
jrpc_add_func ( " verto.bye " , verto__bye_func ) ;
jrpc_add_func ( " verto.answer " , verto__answer_func ) ;
jrpc_add_func ( " verto.subscribe " , verto__subscribe_func ) ;
jrpc_add_func ( " verto.unsubscribe " , verto__unsubscribe_func ) ;
jrpc_add_func ( " verto.broadcast " , verto__broadcast_func ) ;
jrpc_add_func ( " verto.modify " , verto__modify_func ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
}
2020-03-25 03:49:19 +04:00
static int start_jsock ( verto_profile_t * profile , ks_socket_t sock , int family )
2014-06-11 12:48:46 -05:00
{
jsock_t * jsock = NULL ;
int flag = 1 ;
int i ;
2014-10-18 09:53:57 +02:00
# ifndef WIN32
unsigned int len ;
# else
int len ;
# endif
2014-06-11 12:48:46 -05:00
jsock_type_t ptype = PTYPE_CLIENT ;
switch_thread_data_t * td ;
switch_memory_pool_t * pool ;
2014-08-01 23:07:13 +05:00
switch_event_t * s_event ;
2014-06-11 12:48:46 -05:00
switch_core_new_memory_pool ( & pool ) ;
jsock = ( jsock_t * ) switch_core_alloc ( pool , sizeof ( * jsock ) ) ;
jsock - > pool = pool ;
2015-05-28 18:02:21 -05:00
jsock - > family = family ;
if ( family = = PF_INET ) {
len = sizeof ( jsock - > remote_addr ) ;
2014-06-11 12:48:46 -05:00
2015-05-28 18:02:21 -05:00
if ( ( jsock - > client_socket = accept ( sock , ( struct sockaddr * ) & jsock - > remote_addr , & len ) ) < 0 ) {
2018-08-29 03:36:50 -07:00
die_errno ( " ACCEPT FAILED " ) ;
2015-05-28 18:02:21 -05:00
}
} else {
len = sizeof ( jsock - > remote_addr6 ) ;
2014-06-11 12:48:46 -05:00
2015-05-28 18:02:21 -05:00
if ( ( jsock - > client_socket = accept ( sock , ( struct sockaddr * ) & jsock - > remote_addr6 , & len ) ) < 0 ) {
2018-08-29 03:36:50 -07:00
die_errno ( " ACCEPT FAILED " ) ;
2015-05-28 18:02:21 -05:00
}
2014-06-11 12:48:46 -05:00
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
for ( i = 0 ; i < profile - > i ; i + + ) {
if ( profile - > server_socket [ i ] = = sock ) {
if ( profile - > ip [ i ] . secure ) {
ptype = PTYPE_CLIENT_SSL ;
}
break ;
}
}
jsock - > local_sock = sock ;
jsock - > profile = profile ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( zstr ( jsock - > name ) ) {
2015-05-28 18:02:21 -05:00
if ( family = = PF_INET ) {
jsock - > remote_port = ntohs ( jsock - > remote_addr . sin_port ) ;
inet_ntop ( AF_INET , & jsock - > remote_addr . sin_addr , jsock - > remote_host , sizeof ( jsock - > remote_host ) ) ;
jsock - > name = switch_core_sprintf ( pool , " %s:%d " , jsock - > remote_host , jsock - > remote_port ) ;
} else {
jsock - > remote_port = ntohs ( jsock - > remote_addr6 . sin6_port ) ;
inet_ntop ( AF_INET6 , & jsock - > remote_addr6 . sin6_addr , jsock - > remote_host , sizeof ( jsock - > remote_host ) ) ;
2015-06-25 17:34:25 -05:00
jsock - > name = switch_core_sprintf ( pool , " [%s]:%d " , jsock - > remote_host , jsock - > remote_port ) ;
2015-05-28 18:02:21 -05:00
}
2014-06-11 12:48:46 -05:00
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
jsock - > ptype = ptype ;
2016-09-20 14:03:35 -05:00
for ( i = 0 ; i < profile - > conn_acl_count ; i + + ) {
if ( ! switch_check_network_list_ip ( jsock - > remote_host , profile - > conn_acl [ i ] ) ) {
2017-01-06 02:10:15 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s Client Connect from %s:%d refused by ACL %s \n " ,
2016-09-20 14:03:35 -05:00
jsock - > name , jsock - > remote_host , jsock - > remote_port , profile - > conn_acl [ i ] ) ;
goto error ;
}
}
2017-01-06 02:10:15 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s Client Connect from %s:%d accepted \n " ,
2016-09-20 14:03:35 -05:00
jsock - > name , jsock - > remote_host , jsock - > remote_port ) ;
2014-08-01 23:07:13 +05:00
if ( switch_event_create_subclass ( & s_event , SWITCH_EVENT_CUSTOM , MY_EVENT_CLIENT_CONNECT ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( s_event , SWITCH_STACK_BOTTOM , " verto_profile_name " , profile - > name ) ;
2015-06-25 17:34:25 -05:00
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " verto_client_address " , " %s " , jsock - > name ) ;
2014-08-01 23:07:13 +05:00
switch_event_fire ( & s_event ) ;
}
2014-06-11 12:48:46 -05:00
/* no nagle please */
setsockopt ( jsock - > client_socket , IPPROTO_TCP , TCP_NODELAY , ( char * ) & flag , sizeof ( flag ) ) ;
2014-08-16 00:43:20 +05:00
# if defined(SO_KEEPALIVE)
setsockopt ( jsock - > client_socket , SOL_SOCKET , SO_KEEPALIVE , ( void * ) & flag , sizeof ( flag ) ) ;
# endif
flag = 30 ;
# if defined(TCP_KEEPIDLE)
2014-08-16 10:08:39 +08:00
setsockopt ( jsock - > client_socket , IPPROTO_TCP , TCP_KEEPIDLE , ( void * ) & flag , sizeof ( flag ) ) ;
2014-08-16 00:43:20 +05:00
# endif
# if defined(TCP_KEEPINTVL)
2014-08-16 10:08:39 +08:00
setsockopt ( jsock - > client_socket , IPPROTO_TCP , TCP_KEEPINTVL , ( void * ) & flag , sizeof ( flag ) ) ;
2014-08-16 00:43:20 +05:00
# endif
2014-06-11 12:48:46 -05:00
td = switch_core_alloc ( jsock - > pool , sizeof ( * td ) ) ;
td - > alloc = 0 ;
td - > func = client_thread ;
td - > obj = jsock ;
td - > pool = pool ;
switch_mutex_init ( & jsock - > write_mutex , SWITCH_MUTEX_NESTED , jsock - > pool ) ;
2014-07-18 01:03:57 +05:00
switch_mutex_init ( & jsock - > filter_mutex , SWITCH_MUTEX_NESTED , jsock - > pool ) ;
2020-04-13 23:17:37 +00:00
switch_mutex_init ( & jsock - > flag_mutex , SWITCH_MUTEX_NESTED , jsock - > pool ) ;
2014-07-18 01:03:57 +05:00
switch_queue_create ( & jsock - > event_queue , MAX_QUEUE_LEN , jsock - > pool ) ;
2014-06-11 12:48:46 -05:00
switch_thread_rwlock_create ( & jsock - > rwlock , jsock - > pool ) ;
switch_thread_pool_launch_thread ( & td ) ;
return 0 ;
error :
2017-01-06 02:10:15 -05:00
2023-06-12 17:25:37 +03:00
if ( jsock - > client_socket ! = KS_SOCK_INVALID ) {
close_socket ( & jsock - > client_socket ) ;
2014-06-11 12:48:46 -05:00
}
2023-06-12 17:25:37 +03:00
switch_core_destroy_memory_pool ( & pool ) ;
2014-06-11 12:48:46 -05:00
return - 1 ;
}
2020-03-25 03:49:19 +04:00
static ks_socket_t prepare_socket ( ips_t * ips )
2014-06-11 12:48:46 -05:00
{
2020-03-25 03:49:19 +04:00
ks_socket_t sock = KS_SOCK_INVALID ;
2014-10-18 09:53:57 +02:00
# ifndef WIN32
2014-06-11 12:48:46 -05:00
int reuse_addr = 1 ;
2014-10-18 09:53:57 +02:00
# else
char reuse_addr = 1 ;
# endif
2015-05-28 18:02:21 -05:00
int family ;
2014-06-11 12:48:46 -05:00
struct sockaddr_in addr ;
2015-05-28 18:02:21 -05:00
struct sockaddr_in6 addr6 ;
if ( strchr ( ips - > local_ip , ' : ' ) ) {
family = PF_INET6 ;
} else {
family = PF_INET ;
}
2014-06-11 12:48:46 -05:00
2015-05-28 18:02:21 -05:00
if ( ( sock = socket ( family , SOCK_STREAM , IPPROTO_TCP ) ) < 0 ) {
2018-08-29 03:36:50 -07:00
die_errno ( " Socket Error! " ) ;
2014-06-11 12:48:46 -05:00
}
2017-01-06 02:10:15 -05:00
2014-06-11 17:11:47 -05:00
if ( setsockopt ( sock , SOL_SOCKET , SO_REUSEADDR , & reuse_addr , sizeof ( reuse_addr ) ) < 0 ) {
2018-08-29 03:36:50 -07:00
die_errno ( " Socket setsockopt Error! " ) ;
2014-06-11 17:11:47 -05:00
}
2014-06-11 12:48:46 -05:00
2015-05-28 18:02:21 -05:00
if ( family = = PF_INET ) {
memset ( & addr , 0 , sizeof ( addr ) ) ;
addr . sin_family = AF_INET ;
addr . sin_addr . s_addr = inet_addr ( ips - > local_ip ) ;
addr . sin_port = htons ( ips - > local_port ) ;
if ( bind ( sock , ( struct sockaddr * ) & addr , sizeof ( addr ) ) < 0 ) {
2018-08-29 03:36:50 -07:00
die_errno ( " Bind Error! " ) ;
2015-05-28 18:02:21 -05:00
}
} else {
memset ( & addr6 , 0 , sizeof ( addr6 ) ) ;
addr6 . sin6_family = AF_INET6 ;
addr6 . sin6_port = htons ( ips - > local_port ) ;
inet_pton ( AF_INET6 , ips - > local_ip , & ( addr6 . sin6_addr ) ) ;
if ( bind ( sock , ( struct sockaddr * ) & addr6 , sizeof ( addr6 ) ) < 0 ) {
2018-08-29 03:36:50 -07:00
die_errno ( " Bind Error! " ) ;
2015-05-28 18:02:21 -05:00
}
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( listen ( sock , MAXPENDING ) < 0 ) {
2018-08-29 03:36:50 -07:00
die_errno ( " Listen error " ) ;
2014-06-11 12:48:46 -05:00
}
2015-05-28 18:02:21 -05:00
ips - > family = family ;
2014-06-11 12:48:46 -05:00
return sock ;
error :
close_file ( & sock ) ;
2020-03-25 03:49:19 +04:00
return KS_SOCK_INVALID ;
2014-06-11 12:48:46 -05:00
}
static void handle_mcast_sub ( verto_profile_t * profile )
{
2015-06-03 15:54:15 -05:00
int bytes ;
2020-03-25 03:49:19 +04:00
if ( profile - > mcast_sub . sock = = KS_SOCK_INVALID ) {
2015-06-03 15:54:15 -05:00
return ;
}
2015-09-02 13:06:29 -04:00
bytes = ( int ) mcast_socket_recv ( & profile - > mcast_sub , NULL , 0 , 0 ) ;
2014-06-11 12:48:46 -05:00
if ( bytes > 0 ) {
cJSON * json ;
profile - > mcast_sub . buffer [ bytes ] = ' \0 ' ;
if ( ( json = cJSON_Parse ( ( char * ) profile - > mcast_sub . buffer ) ) ) {
jsock_send_event ( json ) ;
cJSON_Delete ( json ) ;
} else {
2018-08-29 03:36:50 -07:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " %s MCAST JSON PARSE ERR: %s \n " , profile - > name , ( char * ) profile - > mcast_sub . buffer ) ;
2014-06-11 12:48:46 -05:00
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
} else {
2018-08-29 03:36:50 -07:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " %s MCAST INVALID READ %d \n " , profile - > name , bytes ) ;
2014-06-11 12:48:46 -05:00
}
}
2014-07-25 00:23:08 +05:00
static int profile_one_loop ( verto_profile_t * profile )
2014-06-11 12:48:46 -05:00
{
2014-07-25 00:23:08 +05:00
switch_waitlist_t pfds [ MAX_BIND + 4 ] ;
int res , x = 0 ;
int i = 0 ;
2014-06-11 12:48:46 -05:00
int max = 2 ;
2014-07-25 00:23:08 +05:00
memset ( & pfds [ 0 ] , 0 , sizeof ( pfds [ 0 ] ) * MAX_BIND + 2 ) ;
2017-01-06 02:10:15 -05:00
2014-07-25 00:23:08 +05:00
for ( i = 0 ; i < profile - > i ; i + + ) {
pfds [ i ] . sock = profile - > server_socket [ i ] ;
pfds [ i ] . events = SWITCH_POLL_READ | SWITCH_POLL_ERROR ;
}
if ( profile - > mcast_ip ) {
pfds [ i ] . sock = profile - > mcast_sub . sock ;
pfds [ i + + ] . events = SWITCH_POLL_READ | SWITCH_POLL_ERROR ;
}
max = i ;
2014-07-26 02:24:10 +05:00
if ( ( res = switch_wait_socklist ( pfds , max , 100 ) ) < 0 ) {
2014-07-25 00:23:08 +05:00
if ( errno ! = EINTR ) {
2018-10-18 04:52:14 -07:00
die_errnof ( " %s POLL FAILED with %d " , profile - > name , res ) ;
2014-07-25 00:23:08 +05:00
}
2018-10-18 04:54:18 -07:00
return 0 ;
2014-07-25 00:23:08 +05:00
}
if ( res = = 0 ) {
return 0 ;
}
2017-01-06 02:10:15 -05:00
2014-07-25 00:23:08 +05:00
for ( x = 0 ; x < max ; x + + ) {
2018-10-18 04:52:14 -07:00
if ( pfds [ x ] . revents & SWITCH_POLL_HUP ) { log_and_exit ( SWITCH_LOG_INFO , " %s POLL HANGUP DETECTED (peer closed its end of socket) \n " , profile - > name ) ; }
2018-08-29 03:36:50 -07:00
if ( pfds [ x ] . revents & SWITCH_POLL_ERROR ) { die ( " %s POLL ERROR \n " , profile - > name ) ; }
if ( pfds [ x ] . revents & SWITCH_POLL_INVALID ) { die ( " %s POLL INVALID SOCKET (not opened or already closed) \n " , profile - > name ) ; }
2014-07-25 00:23:08 +05:00
if ( pfds [ x ] . revents & SWITCH_POLL_READ ) {
2014-12-03 15:06:31 -06:00
if ( profile - > mcast_ip & & pfds [ x ] . sock = = ( switch_os_socket_t ) profile - > mcast_sub . sock ) {
2014-07-25 00:23:08 +05:00
handle_mcast_sub ( profile ) ;
} else {
2015-05-28 18:02:21 -05:00
start_jsock ( profile , pfds [ x ] . sock , profile - > ip [ x ] . family ) ;
2014-07-25 00:23:08 +05:00
}
}
}
return res ;
error :
return - 1 ;
}
2014-06-11 12:48:46 -05:00
static void kill_profile ( verto_profile_t * profile )
{
jsock_t * p ;
2014-09-06 12:06:24 +08:00
verto_vhost_t * h ;
2014-06-11 12:48:46 -05:00
int i ;
profile - > running = 0 ;
//if (switch_thread_rwlock_tryrdlock(profile->rwlock) != SWITCH_STATUS_SUCCESS) {
// return;
//}
switch_mutex_lock ( profile - > mutex ) ;
for ( i = 0 ; i < profile - > i ; i + + ) {
close_socket ( & profile - > server_socket [ i ] ) ;
}
for ( p = profile - > jsock_head ; p ; p = p - > next ) {
close_socket ( & p - > client_socket ) ;
}
2014-09-06 12:06:24 +08:00
h = profile - > vhosts ;
while ( h ) {
if ( h - > rewrites ) {
switch_event_destroy ( & h - > rewrites ) ;
}
h = h - > next ;
}
2014-06-11 12:48:46 -05:00
switch_mutex_unlock ( profile - > mutex ) ;
//switch_thread_rwlock_unlock(profile->rwlock);
}
static void kill_profiles ( void )
{
verto_profile_t * pp ;
int sanity = 50 ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
2017-01-06 02:10:15 -05:00
for ( pp = verto_globals . profile_head ; pp ; pp = pp - > next ) {
2014-06-11 12:48:46 -05:00
kill_profile ( pp ) ;
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
while ( - - sanity > 0 & & verto_globals . profile_threads > 0 ) {
2014-10-18 09:53:57 +02:00
switch_yield ( 100000 ) ;
2014-06-11 12:48:46 -05:00
}
}
2019-07-12 19:59:40 +04:00
static void runtime ( verto_profile_t * profile )
2015-05-28 18:02:21 -05:00
{
int i ;
2015-06-03 15:54:15 -05:00
int listeners = 0 ;
2015-05-28 18:02:21 -05:00
for ( i = 0 ; i < profile - > i ; i + + ) {
//if ((profile->server_socket[i] = prepare_socket(profile->ip[i].local_ip_addr, profile->ip[i].local_port)) < 0) {
2020-03-25 03:49:19 +04:00
if ( ( profile - > server_socket [ i ] = prepare_socket ( & profile - > ip [ i ] ) ) ! = KS_SOCK_INVALID ) {
2015-06-03 15:54:15 -05:00
listeners + + ;
2015-05-28 18:02:21 -05:00
}
}
2017-01-06 02:10:15 -05:00
2015-06-03 15:54:15 -05:00
if ( ! listeners ) {
2018-08-29 03:36:50 -07:00
die ( " %s Client Socket Error! No Listeners! \n " , profile - > name ) ;
2015-06-03 15:54:15 -05:00
}
2015-05-28 18:02:21 -05:00
if ( profile - > mcast_ip ) {
2015-06-03 15:54:15 -05:00
int ok = 1 ;
2015-05-28 18:02:21 -05:00
if ( mcast_socket_create ( profile - > mcast_ip , profile - > mcast_port , & profile - > mcast_sub , MCAST_RECV | MCAST_TTL_HOST ) < 0 ) {
2015-06-03 15:54:15 -05:00
ok + + ;
2015-05-28 18:02:21 -05:00
}
2017-01-06 02:10:15 -05:00
2019-07-12 19:59:40 +04:00
if ( mcast_socket_create ( profile - > mcast_ip , profile - > mcast_port + 1 , & profile - > mcast_pub , MCAST_SEND | MCAST_TTL_HOST ) > 0 ) {
2015-05-28 18:02:21 -05:00
mcast_socket_close ( & profile - > mcast_sub ) ;
2015-06-03 15:54:15 -05:00
ok = 0 ;
2015-05-28 18:02:21 -05:00
}
2015-06-03 15:54:15 -05:00
if ( ok ) {
2018-10-18 04:52:14 -07:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " %s MCAST Bound to %s:%d/%d \n " , profile - > name , profile - > mcast_ip , profile - > mcast_port , profile - > mcast_port + 1 ) ;
2015-06-03 15:54:15 -05:00
} else {
2018-10-18 04:52:14 -07:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " %s MCAST Disabled \n " , profile - > name ) ;
2015-06-03 15:54:15 -05:00
}
2015-05-28 18:02:21 -05:00
}
2017-01-06 02:10:15 -05:00
2015-05-28 18:02:21 -05:00
while ( profile - > running ) {
if ( profile_one_loop ( profile ) < 0 ) {
goto error ;
}
}
error :
2020-03-25 03:49:19 +04:00
if ( profile - > mcast_sub . sock ! = KS_SOCK_INVALID ) {
2015-05-28 18:02:21 -05:00
mcast_socket_close ( & profile - > mcast_sub ) ;
}
2020-03-25 03:49:19 +04:00
if ( profile - > mcast_pub . sock ! = KS_SOCK_INVALID ) {
2015-05-28 18:02:21 -05:00
mcast_socket_close ( & profile - > mcast_pub ) ;
}
}
2014-06-11 12:48:46 -05:00
static void do_shutdown ( void )
{
2017-02-09 17:23:30 -06:00
verto_globals . running = 0 ;
2014-06-11 12:48:46 -05:00
2018-08-29 03:36:50 -07:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Shutting down (SIG %d) \n " , verto_globals . sig ) ;
2014-06-11 12:48:46 -05:00
kill_profiles ( ) ;
unsub_all_jsock ( ) ;
2018-08-29 03:36:50 -07:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Done \n " ) ;
2014-06-11 12:48:46 -05:00
}
2015-05-28 18:02:21 -05:00
static void parse_ip ( char * host , switch_size_t host_len , uint16_t * port , char * input )
2014-06-11 12:48:46 -05:00
{
char * p ;
2015-05-28 18:02:21 -05:00
//struct hostent *hent;
if ( ( p = strchr ( input , ' [ ' ) ) ) {
char * end = switch_find_end_paren ( p , ' [ ' , ' ] ' ) ;
if ( end ) {
p + + ;
strncpy ( host , p , end - p ) ;
if ( * ( end + 1 ) = = ' : ' & & end + 2 < end_of_p ( input ) ) {
end + = 2 ;
2019-07-12 19:59:40 +04:00
if ( * end ) {
2015-05-28 18:02:21 -05:00
* port = ( uint16_t ) atoi ( end ) ;
}
}
} else {
strncpy ( host , " :: " , host_len ) ;
}
} else {
strncpy ( host , input , host_len ) ;
if ( ( p = strrchr ( host , ' : ' ) ) ! = NULL ) {
* p + + = ' \0 ' ;
* port = ( uint16_t ) atoi ( p ) ;
}
2014-06-11 12:48:46 -05:00
}
2015-05-28 18:02:21 -05:00
#if 0
2014-06-11 12:48:46 -05:00
if ( host [ 0 ] < ' 0 ' | | host [ 0 ] > ' 9 ' ) {
// Non-numeric host (at least it doesn't start with one). Convert it to ip addr first
if ( ( hent = gethostbyname ( host ) ) ! = NULL ) {
if ( hent - > h_addrtype = = AF_INET ) {
memcpy ( addr , hent - > h_addr_list [ 0 ] , 4 ) ;
}
}
} else {
* addr = inet_addr ( host ) ;
}
2015-05-28 18:02:21 -05:00
# endif
2014-06-11 12:48:46 -05:00
}
2015-05-28 18:02:21 -05:00
2014-06-11 12:48:46 -05:00
static verto_profile_t * find_profile ( const char * name )
{
verto_profile_t * p , * r = NULL ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
for ( p = verto_globals . profile_head ; p ; p = p - > next ) {
2014-06-11 12:48:46 -05:00
if ( ! strcmp ( name , p - > name ) ) {
r = p ;
break ;
}
}
2014-06-11 17:11:47 -05:00
if ( r & & ( ! r - > in_thread | | ! r - > running ) ) {
2014-06-11 12:48:46 -05:00
r = NULL ;
}
2014-06-11 17:11:47 -05:00
if ( r & & switch_thread_rwlock_tryrdlock ( r - > rwlock ) ! = SWITCH_STATUS_SUCCESS ) {
2014-06-11 12:48:46 -05:00
r = NULL ;
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
return r ;
}
static switch_bool_t profile_exists ( const char * name )
{
switch_bool_t r = SWITCH_FALSE ;
verto_profile_t * p ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
for ( p = verto_globals . profile_head ; p ; p = p - > next ) {
2014-06-11 12:48:46 -05:00
if ( ! strcmp ( p - > name , name ) ) {
r = SWITCH_TRUE ;
break ;
}
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
return r ;
}
static void del_profile ( verto_profile_t * profile )
{
verto_profile_t * p , * last = NULL ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
for ( p = verto_globals . profile_head ; p ; p = p - > next ) {
2014-06-11 12:48:46 -05:00
if ( p = = profile ) {
if ( last ) {
last - > next = p - > next ;
} else {
2017-02-09 17:23:30 -06:00
verto_globals . profile_head = p - > next ;
2014-06-11 12:48:46 -05:00
}
2017-02-09 17:23:30 -06:00
verto_globals . profile_count - - ;
2014-06-11 12:48:46 -05:00
break ;
}
last = p ;
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
}
static switch_status_t add_profile ( verto_profile_t * profile )
{
switch_status_t status = SWITCH_STATUS_FALSE ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
if ( ! profile_exists ( profile - > name ) ) {
status = SWITCH_STATUS_SUCCESS ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( status = = SWITCH_STATUS_SUCCESS ) {
2017-02-09 17:23:30 -06:00
profile - > next = verto_globals . profile_head ;
verto_globals . profile_head = profile ;
verto_globals . profile_count + + ;
2014-06-11 12:48:46 -05:00
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
return status ;
}
static switch_status_t parse_config ( const char * cf )
{
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_xml_t cfg , xml , settings , param , xprofile , xprofiles ;
2014-09-06 12:06:24 +08:00
switch_xml_t xvhosts , xvhost , rewrites , rule ;
2014-06-11 12:48:46 -05:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
if ( ! ( xml = switch_xml_open_cfg ( cf , & cfg , NULL ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Open of %s failed \n " , cf ) ;
return SWITCH_STATUS_TERM ;
}
if ( ( xprofiles = switch_xml_child ( cfg , " profiles " ) ) ) {
for ( xprofile = switch_xml_child ( xprofiles , " profile " ) ; xprofile ; xprofile = xprofile - > next ) {
verto_profile_t * profile ;
switch_memory_pool_t * pool ;
const char * name = switch_xml_attr ( xprofile , " name " ) ;
if ( zstr ( name ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Required field name missing \n " ) ;
continue ;
}
if ( profile_exists ( name ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Profile %s already exists \n " , name ) ;
continue ;
}
switch_core_new_memory_pool ( & pool ) ;
profile = switch_core_alloc ( pool , sizeof ( * profile ) ) ;
profile - > pool = pool ;
profile - > name = switch_core_strdup ( profile - > pool , name ) ;
switch_mutex_init ( & profile - > mutex , SWITCH_MUTEX_NESTED , profile - > pool ) ;
switch_thread_rwlock_create ( & profile - > rwlock , profile - > pool ) ;
add_profile ( profile ) ;
profile - > local_network = " localnet.auto " ;
2020-03-25 03:49:19 +04:00
profile - > mcast_sub . sock = KS_SOCK_INVALID ;
profile - > mcast_pub . sock = KS_SOCK_INVALID ;
2020-08-13 21:08:32 +00:00
profile - > chop_domain = SWITCH_TRUE ;
2016-01-28 12:29:45 -06:00
2014-06-11 12:48:46 -05:00
for ( param = switch_xml_child ( xprofile , " param " ) ; param ; param = param - > next ) {
char * var = NULL ;
char * val = NULL ;
var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! strcasecmp ( var , " bind-local " ) ) {
const char * secure = switch_xml_attr_soft ( param , " secure " ) ;
2019-07-12 19:59:40 +04:00
if ( profile - > i < MAX_BIND ) {
2015-05-28 18:02:21 -05:00
parse_ip ( profile - > ip [ profile - > i ] . local_ip , sizeof ( profile - > ip [ profile - > i ] . local_ip ) , & profile - > ip [ profile - > i ] . local_port , val ) ;
2014-06-11 12:48:46 -05:00
if ( switch_true ( secure ) ) {
profile - > ip [ profile - > i ] . secure = 1 ;
}
profile - > i + + ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Max Bindings Reached! \n " ) ;
}
2017-03-09 13:40:33 -06:00
} else if ( ! strcasecmp ( var , " enable-text " ) ) {
profile - > enable_text = 1 ;
2014-06-11 12:48:46 -05:00
} else if ( ! strcasecmp ( var , " secure-combined " ) ) {
set_string ( profile - > cert , val ) ;
set_string ( profile - > key , val ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Secure key and cert specified \n " ) ;
} else if ( ! strcasecmp ( var , " secure-cert " ) ) {
set_string ( profile - > cert , val ) ;
} else if ( ! strcasecmp ( var , " secure-key " ) ) {
set_string ( profile - > key , val ) ;
} else if ( ! strcasecmp ( var , " secure-chain " ) ) {
set_string ( profile - > chain , val ) ;
2014-06-25 21:18:04 +05:00
} else if ( ! strcasecmp ( var , " inbound-codec-string " ) & & ! zstr ( val ) ) {
2017-01-06 02:10:15 -05:00
profile - > inbound_codec_string = switch_core_strdup ( profile - > pool , val ) ;
2014-06-25 21:18:04 +05:00
} else if ( ! strcasecmp ( var , " outbound-codec-string " ) & & ! zstr ( val ) ) {
2017-01-06 02:10:15 -05:00
profile - > outbound_codec_string = switch_core_strdup ( profile - > pool , val ) ;
2019-04-03 05:08:48 -07:00
} else if ( ! strcasecmp ( var , " auto-jitterbuffer-msec " ) & & ! zstr ( val ) ) {
profile - > jb_msec = switch_core_strdup ( profile - > pool , val ) ;
2014-07-19 00:42:49 +05:00
} else if ( ! strcasecmp ( var , " blind-reg " ) & & ! zstr ( val ) ) {
profile - > blind_reg = switch_true ( val ) ;
2014-06-11 12:48:46 -05:00
} else if ( ! strcasecmp ( var , " userauth " ) & & ! zstr ( val ) ) {
profile - > userauth = switch_core_strdup ( profile - > pool , val ) ;
2020-08-13 21:08:32 +00:00
} else if ( ! strcasecmp ( var , " chop-domain " ) & & ! zstr ( val ) ) {
profile - > chop_domain = switch_true ( val ) ;
2014-06-11 12:48:46 -05:00
} else if ( ! strcasecmp ( var , " root-password " ) & & ! zstr ( val ) ) {
profile - > root_passwd = switch_core_strdup ( profile - > pool , val ) ;
2020-04-05 20:15:12 +00:00
} else if ( ! strcasecmp ( var , " send-auth-password " ) & & ! zstr ( val ) ) {
profile - > send_passwd = switch_true ( val ) ;
2014-06-11 12:48:46 -05:00
} else if ( ! strcasecmp ( var , " context " ) & & ! zstr ( val ) ) {
profile - > context = switch_core_strdup ( profile - > pool , val ) ;
} else if ( ! strcasecmp ( var , " dialplan " ) & & ! zstr ( val ) ) {
profile - > dialplan = switch_core_strdup ( profile - > pool , val ) ;
} else if ( ! strcasecmp ( var , " mcast-ip " ) & & val ) {
profile - > mcast_ip = switch_core_strdup ( profile - > pool , val ) ;
} else if ( ! strcasecmp ( var , " mcast-port " ) & & val ) {
profile - > mcast_port = ( switch_port_t ) atoi ( val ) ;
} else if ( ! strcasecmp ( var , " timer-name " ) & & ! zstr ( var ) ) {
profile - > timer_name = switch_core_strdup ( profile - > pool , val ) ;
2015-04-23 10:45:48 -05:00
} else if ( ! strcasecmp ( var , " force-register-domain " ) & & ! zstr ( val ) ) {
profile - > register_domain = switch_core_strdup ( profile - > pool , val ) ;
2014-06-11 12:48:46 -05:00
} else if ( ! strcasecmp ( var , " local-network " ) & & ! zstr ( val ) ) {
profile - > local_network = switch_core_strdup ( profile - > pool , val ) ;
} else if ( ! strcasecmp ( var , " apply-candidate-acl " ) ) {
if ( profile - > cand_acl_count < SWITCH_MAX_CAND_ACL ) {
profile - > cand_acl [ profile - > cand_acl_count + + ] = switch_core_strdup ( profile - > pool , val ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Max acl records of %d reached \n " , SWITCH_MAX_CAND_ACL ) ;
}
2016-09-20 14:03:35 -05:00
} else if ( ! strcasecmp ( var , " apply-connection-acl " ) ) {
if ( profile - > conn_acl_count < SWITCH_MAX_CAND_ACL ) {
profile - > conn_acl [ profile - > conn_acl_count + + ] = switch_core_strdup ( profile - > pool , val ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Max acl records of %d reached \n " , SWITCH_MAX_CAND_ACL ) ;
}
2014-06-11 12:48:46 -05:00
} else if ( ! strcasecmp ( var , " rtp-ip " ) ) {
if ( zstr ( val ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Invalid RTP IP. \n " ) ;
} else {
2015-05-28 18:02:21 -05:00
if ( strchr ( val , ' : ' ) ) {
if ( profile - > rtpip_index6 < MAX_RTPIP - 1 ) {
profile - > rtpip6 [ profile - > rtpip_index6 + + ] = switch_core_strdup ( profile - > pool , val ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Too many RTP IP. \n " ) ;
}
2014-06-11 12:48:46 -05:00
} else {
2015-05-28 18:02:21 -05:00
if ( profile - > rtpip_index < MAX_RTPIP - 1 ) {
profile - > rtpip [ profile - > rtpip_index + + ] = switch_core_strdup ( profile - > pool , val ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Too many RTP IP. \n " ) ;
}
2014-06-11 12:48:46 -05:00
}
}
} else if ( ! strcasecmp ( var , " ext-rtp-ip " ) ) {
if ( zstr ( val ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Invalid External RTP IP. \n " ) ;
} else {
2018-12-12 01:33:06 +04:00
switch_stun_ip_lookup ( & profile - > extrtpip , val , profile - > pool ) ;
2017-01-06 02:10:15 -05:00
}
2014-06-11 12:48:46 -05:00
} else if ( ! strcasecmp ( var , " debug " ) ) {
if ( val ) {
profile - > debug = atoi ( val ) ;
}
}
}
if ( zstr ( profile - > outbound_codec_string ) ) {
profile - > outbound_codec_string = " opus,vp8 " ;
}
if ( zstr ( profile - > inbound_codec_string ) ) {
2014-06-11 17:11:47 -05:00
profile - > inbound_codec_string = profile - > outbound_codec_string ;
2014-06-11 12:48:46 -05:00
}
2019-04-03 05:08:48 -07:00
if ( zstr ( profile - > jb_msec ) ) {
2020-06-26 21:54:40 +00:00
profile - > jb_msec = " 1p:20p " ;
2019-04-03 05:08:48 -07:00
}
2014-06-11 12:48:46 -05:00
if ( zstr ( profile - > timer_name ) ) {
profile - > timer_name = " soft " ;
}
if ( zstr ( profile - > dialplan ) ) {
profile - > dialplan = " XML " ;
}
if ( zstr ( profile - > context ) ) {
profile - > context = " default " ;
}
if ( zstr ( profile - > ip [ 0 ] . local_ip ) ) switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " %s: local_ip bad \n " , profile - > name ) ;
if ( profile - > ip [ 0 ] . local_port < = 0 ) switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " %s: local_port bad \n " , profile - > name ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( zstr ( profile - > ip [ 0 ] . local_ip ) | | profile - > ip [ 0 ] . local_port < = 0 ) {
del_profile ( profile ) ;
switch_core_destroy_memory_pool ( & pool ) ;
} else {
int i ;
for ( i = 0 ; i < profile - > i ; i + + ) {
2016-09-20 14:03:35 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
2017-01-06 02:10:15 -05:00
strchr ( profile - > ip [ i ] . local_ip , ' : ' ) ? " %s Bound to [%s]:%d \n " : " %s Bound to %s:%d \n " ,
2014-06-11 12:48:46 -05:00
profile - > name , profile - > ip [ i ] . local_ip , profile - > ip [ i ] . local_port ) ;
}
}
2014-09-06 12:06:24 +08:00
/* parse vhosts */
/* WARNNING: Experimental feature, DO NOT use until we remove this warnning!! */
if ( ( xvhosts = switch_xml_child ( xprofile , " vhosts " ) ) ) {
verto_vhost_t * vhost_tail = NULL ;
for ( xvhost = switch_xml_child ( xvhosts , " vhost " ) ; xvhost ; xvhost = xvhost - > next ) {
verto_vhost_t * vhost ;
const char * domain = switch_xml_attr ( xvhost , " domain " ) ;
if ( zstr ( domain ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Required field domain missing \n " ) ;
continue ;
}
vhost = switch_core_alloc ( profile - > pool , sizeof ( * vhost ) ) ;
memset ( vhost , 0 , sizeof ( * vhost ) ) ;
vhost - > pool = profile - > pool ;
vhost - > domain = switch_core_strdup ( profile - > pool , domain ) ;
if ( ! vhost_tail ) {
profile - > vhosts = vhost ;
} else {
vhost_tail - > next = vhost ;
}
vhost_tail = vhost ;
for ( param = switch_xml_child ( xvhost , " param " ) ; param ; param = param - > next ) {
char * var = NULL ;
char * val = NULL ;
var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " alias " ) ) {
vhost - > alias = switch_core_strdup ( vhost - > pool , val ) ;
} else if ( ! strcasecmp ( var , " root " ) ) {
vhost - > root = switch_core_strdup ( vhost - > pool , val ) ;
2016-08-22 15:19:56 -05:00
} else if ( ! strcasecmp ( var , " script-root " ) ) {
2014-09-06 12:06:24 +08:00
vhost - > script_root = switch_core_strdup ( vhost - > pool , val ) ;
} else if ( ! strcasecmp ( var , " index " ) ) {
vhost - > index = switch_core_strdup ( vhost - > pool , val ) ;
} else if ( ! strcasecmp ( var , " auth-realm " ) ) {
vhost - > auth_realm = switch_core_strdup ( vhost - > pool , val ) ;
} else if ( ! strcasecmp ( var , " auth-user " ) ) {
vhost - > auth_user = switch_core_strdup ( vhost - > pool , val ) ;
} else if ( ! strcasecmp ( var , " auth-pass " ) ) {
vhost - > auth_pass = switch_core_strdup ( vhost - > pool , val ) ;
}
}
if ( zstr ( vhost - > root ) ) {
vhost - > root = SWITCH_GLOBAL_dirs . htdocs_dir ;
}
if ( zstr ( vhost - > script_root ) ) {
2014-11-03 14:15:04 -06:00
vhost - > script_root = SWITCH_GLOBAL_dirs . script_dir ;
2014-09-06 12:06:24 +08:00
}
if ( zstr ( vhost - > index ) ) {
vhost - > index = " index.html " ;
}
if ( ( rewrites = switch_xml_child ( xvhost , " rewrites " ) ) ) {
if ( switch_event_create ( & vhost - > rewrites , SWITCH_EVENT_CLONE ) = = SWITCH_STATUS_SUCCESS ) {
for ( rule = switch_xml_child ( rewrites , " rule " ) ; rule ; rule = rule - > next ) {
char * expr = NULL ;
char * val = NULL ;
expr = ( char * ) switch_xml_attr_soft ( rule , " expression " ) ;
val = ( char * ) switch_xml_attr_soft ( rule , " value " ) ;
if ( zstr ( expr ) ) continue ;
switch_event_add_header_string ( vhost - > rewrites , SWITCH_STACK_BOTTOM , expr , val ) ;
}
}
} // rewrites
} // xvhost
} // xvhosts
} // xprofile
} // xprofiles
2014-06-11 12:48:46 -05:00
if ( ( settings = switch_xml_child ( cfg , " settings " ) ) ) {
for ( param = switch_xml_child ( settings , " param " ) ; param ; param = param - > next ) {
char * var = NULL ;
char * val = NULL ;
var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " debug " ) ) {
if ( val ) {
2017-02-09 17:23:30 -06:00
verto_globals . debug = atoi ( val ) ;
2014-06-11 12:48:46 -05:00
}
} else if ( ! strcasecmp ( var , " enable-presence " ) & & val ) {
2017-02-09 17:23:30 -06:00
verto_globals . enable_presence = switch_true ( val ) ;
2020-04-05 20:15:12 +00:00
} else if ( ! strcasecmp ( var , " send-auth-password " ) & & ! zstr ( val ) ) {
verto_globals . send_passwd = switch_true ( val ) ;
2014-07-18 01:03:57 +05:00
} else if ( ! strcasecmp ( var , " enable-fs-events " ) & & val ) {
2017-02-09 17:23:30 -06:00
verto_globals . enable_fs_events = switch_true ( val ) ;
2014-06-11 12:48:46 -05:00
} else if ( ! strcasecmp ( var , " detach-timeout-sec " ) & & val ) {
int tmp = atoi ( val ) ;
if ( tmp > 0 ) {
2017-02-09 17:23:30 -06:00
verto_globals . detach_timeout = tmp ;
2014-06-11 12:48:46 -05:00
}
2020-03-25 03:49:19 +04:00
} else if ( ! strcasecmp ( var , " kslog " ) ) {
if ( val ) {
verto_globals . kslog_on = switch_true ( val ) ;
}
2014-06-11 12:48:46 -05:00
}
}
}
switch_xml_free ( xml ) ;
return status ;
}
static int init ( void )
{
verto_profile_t * p ;
parse_config ( " verto.conf " ) ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
2017-01-06 02:10:15 -05:00
for ( p = verto_globals . profile_head ; p ; p = p - > next ) {
2014-06-11 12:48:46 -05:00
verto_init_ssl ( p ) ;
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
verto_globals . running = 1 ;
2014-06-11 12:48:46 -05:00
return 0 ;
}
#if 0
static void print_status ( verto_profile_t * profile , switch_stream_handle_t * stream )
{
jsock_t * p ;
stream - > write_function ( stream , " REMOTE \t \t \t LOCAL \n " ) ;
for ( p = profile - > jsock_head ; p ; p = p - > next ) {
if ( p - > ptype & PTYPE_CLIENT ) {
int i ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
for ( i = 0 ; i < profile - > i ; i + + ) {
if ( profile - > server_socket [ i ] = = p - > local_sock ) {
stream - > write_function ( stream , " %s \t %s:%d \n " , p - > name , profile - > ip [ i ] . local_ip , profile - > ip [ i ] . local_port ) ;
}
}
}
}
}
# endif
2014-07-31 23:04:10 +05:00
typedef switch_status_t ( * verto_command_t ) ( char * * argv , int argc , switch_stream_handle_t * stream ) ;
static switch_status_t cmd_status ( char * * argv , int argc , switch_stream_handle_t * stream )
{
verto_profile_t * profile = NULL ;
jsock_t * jsock ;
2014-09-06 12:06:24 +08:00
verto_vhost_t * vhost ;
2014-07-31 23:04:10 +05:00
int cp = 0 ;
int cc = 0 ;
const char * line = " ================================================================================================= " ;
2014-10-18 09:53:57 +02:00
int i ;
2014-06-11 12:48:46 -05:00
2014-07-31 23:04:10 +05:00
stream - > write_function ( stream , " %25s \t %s \t %40s \t %s \n " , " Name " , " Type " , " Data " , " State " ) ;
stream - > write_function ( stream , " %s \n " , line ) ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
for ( profile = verto_globals . profile_head ; profile ; profile = profile - > next ) {
2018-04-04 11:50:14 +00:00
for ( i = 0 ; i < profile - > i ; i + + ) {
2015-06-25 17:34:25 -05:00
char * tmpurl = switch_mprintf ( strchr ( profile - > ip [ i ] . local_ip , ' : ' ) ? " %s:[%s]:%d " : " %s:%s:%d " ,
( profile - > ip [ i ] . secure = = 1 ) ? " wss " : " ws " , profile - > ip [ i ] . local_ip , profile - > ip [ i ] . local_port ) ;
2020-03-25 03:49:19 +04:00
stream - > write_function ( stream , " %25s \t %s \t %40s \t %s \n " , profile - > name , " profile " , tmpurl , ( profile - > server_socket [ i ] ! = KS_SOCK_INVALID ) ? " RUNNING " : " DOWN " ) ;
2014-09-06 12:06:24 +08:00
switch_safe_free ( tmpurl ) ;
2014-07-31 23:04:10 +05:00
}
cp + + ;
switch_mutex_lock ( profile - > mutex ) ;
2014-09-06 12:06:24 +08:00
for ( vhost = profile - > vhosts ; vhost ; vhost = vhost - > next ) {
char * tmpname = switch_mprintf ( " %s::%s " , profile - > name , vhost - > domain ) ;
stream - > write_function ( stream , " %25s \t %s \t %40s \t %s (%s) \n " , tmpname , " vhost " , vhost - > root , vhost - > auth_user ? " AUTH " : " NOAUTH " , vhost - > auth_user ? vhost - > auth_user : " " ) ;
switch_safe_free ( tmpname ) ;
}
for ( jsock = profile - > jsock_head ; jsock ; jsock = jsock - > next ) {
2014-07-31 23:04:10 +05:00
char * tmpname = switch_mprintf ( " %s::%s@%s " , profile - > name , jsock - > id , jsock - > domain ) ;
stream - > write_function ( stream , " %25s \t %s \t %40s \t %s (%s) \n " , tmpname , " client " , jsock - > name , ( ! zstr ( jsock - > uid ) ) ? " CONN_REG " : " CONN_NO_REG " , ( jsock - > ptype & PTYPE_CLIENT_SSL ) ? " WSS " : " WS " ) ;
cc + + ;
2014-09-06 12:06:24 +08:00
switch_safe_free ( tmpname ) ;
2014-07-31 23:04:10 +05:00
}
switch_mutex_unlock ( profile - > mutex ) ;
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-07-31 23:04:10 +05:00
stream - > write_function ( stream , " %s \n " , line ) ;
stream - > write_function ( stream , " %d profile%s , %d client%s \n " , cp , cp = = 1 ? " " : " s " , cc , cc = = 1 ? " " : " s " ) ;
return SWITCH_STATUS_SUCCESS ;
}
2020-06-11 23:24:43 +00:00
static switch_status_t cmd_announce ( char * * argv , int argc , switch_stream_handle_t * stream )
{
verto_profile_t * profile = NULL ;
jsock_t * jsock ;
switch_mutex_lock ( verto_globals . mutex ) ;
for ( profile = verto_globals . profile_head ; profile ; profile = profile - > next ) {
switch_mutex_lock ( profile - > mutex ) ;
for ( jsock = profile - > jsock_head ; jsock ; jsock = jsock - > next ) {
cJSON * params = NULL ;
cJSON * array , * msg = jrpc_new_req ( " verto.announce " , 0 , & params ) ;
int i ;
array = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < argc ; i + + ) {
cJSON_AddItemToArray ( array , cJSON_CreateString ( argv [ i ] ) ) ;
}
cJSON_AddItemToObject ( params , " msg " , array ) ;
jsock_queue_event ( jsock , & msg , SWITCH_TRUE ) ;
}
switch_mutex_unlock ( profile - > mutex ) ;
}
switch_mutex_unlock ( verto_globals . mutex ) ;
stream - > write_function ( stream , " +OK \n " ) ;
return SWITCH_STATUS_SUCCESS ;
}
2014-07-31 23:04:10 +05:00
static switch_status_t cmd_xml_status ( char * * argv , int argc , switch_stream_handle_t * stream )
2014-06-11 12:48:46 -05:00
{
2014-07-31 23:04:10 +05:00
verto_profile_t * profile = NULL ;
jsock_t * jsock ;
const char * header = " <?xml version= \" 1.0 \" encoding= \" ISO-8859-1 \" ?> " ;
2014-10-18 09:53:57 +02:00
int i ;
2014-07-31 23:04:10 +05:00
stream - > write_function ( stream , " %s \n " , header ) ;
stream - > write_function ( stream , " <profiles> \n " ) ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
for ( profile = verto_globals . profile_head ; profile ; profile = profile - > next ) {
2014-10-18 09:53:57 +02:00
for ( i = 0 ; i < profile - > i ; i + + ) {
2015-06-25 17:34:25 -05:00
char * tmpurl = switch_mprintf ( strchr ( profile - > ip [ i ] . local_ip , ' : ' ) ? " %s:[%s]:%d " : " %s:%s:%d " ,
( profile - > ip [ i ] . secure = = 1 ) ? " wss " : " ws " , profile - > ip [ i ] . local_ip , profile - > ip [ i ] . local_port ) ;
2014-07-31 23:04:10 +05:00
stream - > write_function ( stream , " <profile> \n <name>%s</name> \n <type>%s</type> \n <data>%s</data> \n <state>%s</state> \n </profile> \n " , profile - > name , " profile " , tmpurl , ( profile - > running ) ? " RUNNING " : " DOWN " ) ;
2014-09-06 12:06:24 +08:00
switch_safe_free ( tmpurl ) ;
2014-07-31 23:04:10 +05:00
}
2014-06-11 12:48:46 -05:00
2014-07-31 23:04:10 +05:00
switch_mutex_lock ( profile - > mutex ) ;
for ( jsock = profile - > jsock_head ; jsock ; jsock = jsock - > next ) {
char * tmpname = switch_mprintf ( " %s@%s " , jsock - > id , jsock - > domain ) ;
stream - > write_function ( stream , " <client> \n <profile>%s</profile> \n <name>%s</name> \n <type>%s</type> \n <data>%s</data> \n <state>%s (%s)</state> \n </client> \n " , profile - > name , tmpname , " client " , jsock - > name ,
( ! zstr ( jsock - > uid ) ) ? " CONN_REG " : " CONN_NO_REG " , ( jsock - > ptype & PTYPE_CLIENT_SSL ) ? " WSS " : " WS " ) ;
2014-09-06 12:06:24 +08:00
switch_safe_free ( tmpname ) ;
2014-07-31 23:04:10 +05:00
}
switch_mutex_unlock ( profile - > mutex ) ;
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-07-31 23:04:10 +05:00
stream - > write_function ( stream , " </profiles> \n " ) ;
return SWITCH_STATUS_SUCCESS ;
}
2023-07-08 06:29:23 -05:00
static cJSON * json_status ( void )
2020-04-23 21:25:21 +00:00
{
cJSON * obj , * profiles , * jprofile , * users , * user ;
verto_profile_t * profile = NULL ;
jsock_t * jsock ;
int i ;
obj = cJSON_CreateObject ( ) ;
profiles = cJSON_CreateArray ( ) ;
cJSON_AddItemToObject ( obj , " profiles " , profiles ) ;
switch_mutex_lock ( verto_globals . mutex ) ;
for ( profile = verto_globals . profile_head ; profile ; profile = profile - > next ) {
for ( i = 0 ; i < profile - > i ; i + + ) {
char * tmpurl = switch_mprintf ( strchr ( profile - > ip [ i ] . local_ip , ' : ' ) ? " %s:[%s]:%d " : " %s:%s:%d " ,
( profile - > ip [ i ] . secure = = 1 ) ? " wss " : " ws " , profile - > ip [ i ] . local_ip , profile - > ip [ i ] . local_port ) ;
jprofile = cJSON_CreateObject ( ) ;
cJSON_AddItemToObject ( jprofile , " name " , cJSON_CreateString ( profile - > name ) ) ;
cJSON_AddItemToObject ( jprofile , " id " , cJSON_CreateString ( tmpurl ) ) ;
cJSON_AddItemToObject ( jprofile , " type " , cJSON_CreateString ( profile - > ip [ i ] . secure = = 1 ? " SECURE " : " BASIC " ) ) ;
cJSON_AddItemToObject ( jprofile , " state " , cJSON_CreateString ( ( profile - > running ) ? " RUNNING " : " DOWN " ) ) ;
cJSON_AddItemToArray ( profiles , jprofile ) ;
switch_safe_free ( tmpurl ) ;
users = cJSON_CreateArray ( ) ;
cJSON_AddItemToObject ( jprofile , " users " , users ) ;
switch_mutex_lock ( profile - > mutex ) ;
for ( jsock = profile - > jsock_head ; jsock ; jsock = jsock - > next ) {
char * tmpname = switch_mprintf ( " %s@%s " , jsock - > id , jsock - > domain ) ;
if ( ! ! profile - > ip [ i ] . secure ! = ! ! ( jsock - > ptype & PTYPE_CLIENT_SSL ) ) {
continue ;
}
user = cJSON_CreateObject ( ) ;
cJSON_AddItemToObject ( user , " user " , cJSON_CreateString ( jsock - > id ) ) ;
cJSON_AddItemToObject ( user , " domain " , cJSON_CreateString ( jsock - > domain ) ) ;
cJSON_AddItemToObject ( user , " entity " , cJSON_CreateString ( tmpname ) ) ;
cJSON_AddItemToObject ( user , " type " , cJSON_CreateString ( ( jsock - > ptype & PTYPE_CLIENT_SSL ) ? " WSS " : " WS " ) ) ;
cJSON_AddItemToObject ( user , " remoteHost " , cJSON_CreateString ( jsock - > name ) ) ;
cJSON_AddItemToObject ( user , " state " , cJSON_CreateString ( ( ! zstr ( jsock - > uid ) ) ? " CONN_REG " : " CONN_NO_REG " ) ) ;
cJSON_AddItemToArray ( users , user ) ;
switch_safe_free ( tmpname ) ;
}
switch_mutex_unlock ( profile - > mutex ) ;
}
}
switch_mutex_unlock ( verto_globals . mutex ) ;
return obj ;
}
static switch_status_t cmd_json_status ( char * * argv , int argc , switch_stream_handle_t * stream )
{
cJSON * record ;
char * json ;
record = json_status ( ) ;
json = cJSON_Print ( record ) ;
//json = cJSON_PrintUnformatted(record);
stream - > write_function ( stream , " %s \n " , json ) ;
switch_safe_free ( json ) ;
return SWITCH_STATUS_SUCCESS ;
}
2014-07-31 23:04:10 +05:00
SWITCH_STANDARD_API ( verto_function )
{
char * argv [ 1024 ] = { 0 } ;
2014-06-11 12:48:46 -05:00
int argc = 0 ;
2014-07-31 23:04:10 +05:00
char * mycmd = NULL ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
verto_command_t func = NULL ;
int lead = 1 ;
static const char usage_string [ ] = " USAGE: \n "
" -------------------------------------------------------------------------------- \n "
2020-04-23 21:25:21 +00:00
" verto [status|xmlstatus|jsonstatus] \n "
2014-07-31 23:04:10 +05:00
" verto help \n "
2020-04-01 00:31:23 +00:00
" verto debug [0-10] \n "
2020-05-08 01:20:14 +00:00
" verto perm <sessid> <type> <value> \n "
2020-05-09 02:03:19 +00:00
" verto noperm <sessid> <type> <value> \n "
2014-07-31 23:04:10 +05:00
" -------------------------------------------------------------------------------- \n " ;
2014-06-11 12:48:46 -05:00
2014-07-31 23:04:10 +05:00
if ( zstr ( cmd ) ) {
stream - > write_function ( stream , " %s " , usage_string ) ;
goto done ;
2014-06-11 12:48:46 -05:00
}
2014-07-31 23:04:10 +05:00
if ( ! ( mycmd = strdup ( cmd ) ) ) {
status = SWITCH_STATUS_MEMERR ;
goto done ;
2014-06-11 12:48:46 -05:00
}
2014-07-31 23:04:10 +05:00
if ( ! ( argc = switch_separate_string ( mycmd , ' ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ) | | ! argv [ 0 ] ) {
stream - > write_function ( stream , " %s " , usage_string ) ;
goto done ;
}
if ( ! strcasecmp ( argv [ 0 ] , " help " ) ) {
stream - > write_function ( stream , " %s " , usage_string ) ;
goto done ;
2020-05-08 01:20:14 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " perm " ) ) {
status = add_perm ( argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , SWITCH_TRUE ) ;
if ( status = = SWITCH_STATUS_SUCCESS ) {
stream - > write_function ( stream , " +OK " ) ;
} else {
stream - > write_function ( stream , " -ERR " ) ;
}
status = SWITCH_STATUS_SUCCESS ;
goto done ;
} else if ( ! strcasecmp ( argv [ 0 ] , " noperm " ) ) {
status = add_perm ( argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , SWITCH_FALSE ) ;
if ( status = = SWITCH_STATUS_SUCCESS ) {
stream - > write_function ( stream , " +OK " ) ;
} else {
stream - > write_function ( stream , " -ERR " ) ;
}
status = SWITCH_STATUS_SUCCESS ;
goto done ;
2020-06-11 23:24:43 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " announce " ) ) {
func = cmd_announce ;
2014-07-31 23:04:10 +05:00
} else if ( ! strcasecmp ( argv [ 0 ] , " status " ) ) {
func = cmd_status ;
} else if ( ! strcasecmp ( argv [ 0 ] , " xmlstatus " ) ) {
func = cmd_xml_status ;
2020-04-23 21:25:21 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " jsonstatus " ) ) {
func = cmd_json_status ;
2020-04-01 00:31:23 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " debug " ) ) {
if ( argv [ 1 ] ) {
int tmp = atoi ( argv [ 1 ] ) ;
if ( tmp > = 0 & & tmp < = 10 ) {
verto_globals . debug = tmp ;
}
}
stream - > write_function ( stream , " Debug Level: %d \n " , verto_globals . debug ) ;
goto done ;
} else if ( ! strcasecmp ( argv [ 0 ] , " debug-level " ) ) {
if ( argv [ 1 ] ) {
verto_globals . debug_level = switch_log_str2level ( argv [ 1 ] ) ;
}
stream - > write_function ( stream , " Debug Level: %s \n " , switch_log_level2str ( verto_globals . debug_level ) ) ;
goto done ;
2014-07-31 23:04:10 +05:00
}
if ( func ) {
status = func ( & argv [ lead ] , argc - lead , stream ) ;
} else {
stream - > write_function ( stream , " Unknown Command [%s] \n " , argv [ 0 ] ) ;
}
done :
switch_safe_free ( mycmd ) ;
return status ;
2014-06-11 12:48:46 -05:00
}
2014-07-31 23:04:10 +05:00
2014-06-11 12:48:46 -05:00
static void * SWITCH_THREAD_FUNC profile_thread ( switch_thread_t * thread , void * obj )
{
verto_profile_t * profile = ( verto_profile_t * ) obj ;
int sanity = 50 ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
verto_globals . profile_threads + + ;
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
profile - > in_thread = 1 ;
profile - > running = 1 ;
runtime ( profile ) ;
profile - > running = 0 ;
2016-09-20 14:03:35 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " profile %s shutdown, Waiting for %d threads \n " , profile - > name , profile - > jsock_count ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
while ( - - sanity > 0 & & profile - > jsock_count > 0 ) {
2014-10-18 09:53:57 +02:00
switch_yield ( 100000 ) ;
2014-06-11 12:48:46 -05:00
}
verto_deinit_ssl ( profile ) ;
del_profile ( profile ) ;
switch_thread_rwlock_wrlock ( profile - > rwlock ) ;
2016-09-20 14:03:35 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s Thread ending \n " , profile - > name ) ;
2014-06-11 12:48:46 -05:00
switch_thread_rwlock_unlock ( profile - > rwlock ) ;
profile - > in_thread = 0 ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
verto_globals . profile_threads - - ;
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
return NULL ;
}
static void run_profile_thread ( verto_profile_t * profile ) {
switch_thread_data_t * td ;
td = switch_core_alloc ( profile - > pool , sizeof ( * td ) ) ;
td - > alloc = 0 ;
td - > func = profile_thread ;
td - > obj = profile ;
td - > pool = profile - > pool ;
switch_thread_pool_launch_thread ( & td ) ;
}
static void run_profiles ( void )
{
verto_profile_t * p ;
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
for ( p = verto_globals . profile_head ; p ; p = p - > next ) {
2014-06-11 12:48:46 -05:00
if ( ! p - > in_thread ) {
run_profile_thread ( p ) ;
}
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
}
//// ENDPOINT
2015-09-23 10:35:45 -05:00
2014-06-11 12:48:46 -05:00
static switch_call_cause_t verto_outgoing_channel ( switch_core_session_t * session ,
switch_event_t * var_event ,
switch_caller_profile_t * outbound_profile ,
2017-01-06 02:10:15 -05:00
switch_core_session_t * * new_session ,
switch_memory_pool_t * * pool ,
2014-06-11 12:48:46 -05:00
switch_originate_flag_t flags ,
switch_call_cause_t * cancel_cause ) ;
switch_io_routines_t verto_io_routines = {
/*.outgoing_channel */ verto_outgoing_channel
} ;
2016-07-10 22:25:14 -05:00
switch_io_routines_t verto_io_override = {
/*.outgoing_channel */ NULL ,
/*.read_frame */ NULL ,
/*.write_frame */ NULL ,
/*.kill_channel */ NULL ,
/*.send_dtmf */ NULL ,
/*.receive_message */ NULL ,
/*.receive_event */ NULL ,
/*.state_change */ NULL ,
/*.read_video_frame */ NULL ,
/*.write_video_frame */ NULL ,
/*.read_text_frame */ verto_read_text_frame ,
/*.write_text_frame */ verto_write_text_frame ,
/*.state_run*/ NULL ,
/*.get_jb*/ NULL
} ;
static switch_status_t verto_read_text_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id )
{
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
switch_status_t status ;
2017-01-06 02:10:15 -05:00
2017-03-13 11:06:28 -05:00
if ( ! tech_pvt - > text_read_buffer ) {
return SWITCH_STATUS_FALSE ;
}
2016-07-10 22:25:14 -05:00
switch_mutex_lock ( tech_pvt - > text_cond_mutex ) ;
2020-02-25 21:45:38 +00:00
switch_thread_cond_timedwait ( tech_pvt - > text_cond , tech_pvt - > text_cond_mutex , 100000 ) ;
2016-07-10 22:25:14 -05:00
switch_mutex_unlock ( tech_pvt - > text_cond_mutex ) ;
* frame = & tech_pvt - > text_read_frame ;
( * frame ) - > flags = 0 ;
switch_mutex_lock ( tech_pvt - > text_read_mutex ) ;
if ( switch_buffer_inuse ( tech_pvt - > text_read_buffer ) ) {
status = SWITCH_STATUS_SUCCESS ;
tech_pvt - > text_read_frame . datalen = switch_buffer_read ( tech_pvt - > text_read_buffer , tech_pvt - > text_read_frame . data , 100 ) ;
} else {
( * frame ) - > flags | = SFF_CNG ;
tech_pvt - > text_read_frame . datalen = 2 ;
status = SWITCH_STATUS_BREAK ;
}
switch_mutex_unlock ( tech_pvt - > text_read_mutex ) ;
return status ;
}
static switch_status_t verto_write_text_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id )
{
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
switch_mutex_lock ( tech_pvt - > text_write_mutex ) ;
2017-01-06 02:10:15 -05:00
2016-07-10 22:25:14 -05:00
if ( frame ) {
switch_buffer_write ( tech_pvt - > text_write_buffer , frame - > data , frame - > datalen ) ;
}
if ( switch_buffer_inuse ( tech_pvt - > text_write_buffer ) ) {
switch_byte_t data [ SWITCH_RTP_MAX_BUF_LEN ] = " " ;
2022-01-07 15:36:46 +03:00
if ( switch_buffer_read ( tech_pvt - > text_write_buffer , data , 100 ) ) {
2016-07-10 22:25:14 -05:00
cJSON * obj = NULL , * txt = NULL , * params = NULL ;
jsock_t * jsock ;
obj = jrpc_new_req ( " verto.info " , tech_pvt - > call_id , & params ) ;
txt = json_add_child_obj ( params , " txt " , NULL ) ;
cJSON_AddItemToObject ( txt , " chars " , cJSON_CreateString ( ( char * ) data ) ) ;
if ( ( jsock = get_jsock ( tech_pvt - > jsock_uuid ) ) ) {
jsock_queue_event ( jsock , & obj , SWITCH_TRUE ) ;
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
} else {
cJSON_Delete ( obj ) ;
}
}
}
2017-01-06 02:10:15 -05:00
2016-07-10 22:25:14 -05:00
switch_mutex_unlock ( tech_pvt - > text_write_mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
static void set_text_funcs ( switch_core_session_t * session )
{
2017-03-13 11:06:28 -05:00
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
2016-07-10 22:25:14 -05:00
2017-03-13 11:06:28 -05:00
if ( ! tech_pvt | | tech_pvt - > text_read_buffer ) {
return ;
}
if ( ( switch_core_session_override_io_routines ( session , & verto_io_override ) = = SWITCH_STATUS_SUCCESS ) ) {
2016-07-10 22:25:14 -05:00
tech_pvt - > text_read_frame . data = tech_pvt - > text_read_frame_data ;
switch_mutex_init ( & tech_pvt - > text_read_mutex , SWITCH_MUTEX_NESTED , tech_pvt - > pool ) ;
switch_mutex_init ( & tech_pvt - > text_write_mutex , SWITCH_MUTEX_NESTED , tech_pvt - > pool ) ;
switch_mutex_init ( & tech_pvt - > text_cond_mutex , SWITCH_MUTEX_NESTED , tech_pvt - > pool ) ;
switch_thread_cond_create ( & tech_pvt - > text_cond , tech_pvt - > pool ) ;
switch_buffer_create_dynamic ( & tech_pvt - > text_read_buffer , 512 , 1024 , 0 ) ;
switch_buffer_create_dynamic ( & tech_pvt - > text_write_buffer , 512 , 1024 , 0 ) ;
2016-10-05 11:05:32 -04:00
switch_channel_set_flag ( switch_core_session_get_channel ( session ) , CF_HAS_TEXT ) ;
2016-07-10 22:25:14 -05:00
switch_core_session_start_text_thread ( session ) ;
}
}
2014-06-11 12:48:46 -05:00
static char * verto_get_dial_string ( const char * uid , switch_stream_handle_t * rstream )
{
jsock_t * jsock ;
verto_profile_t * profile ;
switch_stream_handle_t * use_stream = NULL , stream = { 0 } ;
char * gen_uid = NULL ;
int hits = 0 ;
if ( ! strchr ( uid , ' @ ' ) ) {
gen_uid = switch_mprintf ( " %s@%s " , uid , switch_core_get_domain ( SWITCH_FALSE ) ) ;
uid = gen_uid ;
}
if ( rstream ) {
use_stream = rstream ;
} else {
SWITCH_STANDARD_STREAM ( stream ) ;
use_stream = & stream ;
}
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
for ( profile = verto_globals . profile_head ; profile ; profile = profile - > next ) {
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_mutex_lock ( profile - > mutex ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
for ( jsock = profile - > jsock_head ; jsock ; jsock = jsock - > next ) {
2014-07-24 02:44:34 -04:00
if ( jsock - > ready & & ! zstr ( jsock - > uid ) & & ! zstr ( uid ) & & ! strcmp ( uid , jsock - > uid ) ) {
2014-06-11 12:48:46 -05:00
use_stream - > write_function ( use_stream , " %s/u:%s, " , EP_NAME , jsock - > uuid_str ) ;
hits + + ;
}
}
switch_mutex_unlock ( profile - > mutex ) ;
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
switch_safe_free ( gen_uid ) ;
if ( ! hits ) {
use_stream - > write_function ( use_stream , " error/user_not_registered " ) ;
}
if ( use_stream - > data ) {
char * p = use_stream - > data ;
if ( end_of ( p ) = = ' , ' ) {
end_of ( p ) = ' \0 ' ;
}
}
return use_stream - > data ;
}
SWITCH_STANDARD_API ( verto_contact_function )
{
char * uid = ( char * ) cmd ;
if ( ! zstr ( uid ) ) {
verto_get_dial_string ( uid , stream ) ;
}
return SWITCH_STATUS_SUCCESS ;
}
static switch_call_cause_t verto_outgoing_channel ( switch_core_session_t * session ,
switch_event_t * var_event ,
switch_caller_profile_t * outbound_profile ,
2017-01-06 02:10:15 -05:00
switch_core_session_t * * new_session ,
switch_memory_pool_t * * pool ,
2014-06-11 12:48:46 -05:00
switch_originate_flag_t flags ,
switch_call_cause_t * cancel_cause )
{
switch_call_cause_t cause = SWITCH_CAUSE_CHANNEL_UNACCEPTABLE ;
char * dest = NULL ;
2015-09-23 10:35:45 -05:00
PROTECT_INTERFACE ( verto_endpoint_interface ) ;
2014-06-11 12:48:46 -05:00
if ( ! zstr ( outbound_profile - > destination_number ) ) {
dest = strdup ( outbound_profile - > destination_number ) ;
}
2014-07-18 22:05:07 +05:00
2014-06-11 12:48:46 -05:00
if ( zstr ( dest ) ) {
goto end ;
}
if ( ! switch_stristr ( " u: " , dest ) ) {
char * dial_str = verto_get_dial_string ( dest , NULL ) ;
2014-07-18 22:05:07 +05:00
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , " verto_orig_dest " , dest ) ;
if ( zstr ( switch_event_get_header ( var_event , " origination_callee_id_number " ) ) ) {
2019-07-12 19:59:40 +04:00
char * p ;
2014-07-18 22:05:07 +05:00
char * trimmed_dest = strdup ( dest ) ;
2019-07-12 19:59:40 +04:00
switch_assert ( trimmed_dest ) ;
p = strchr ( trimmed_dest , ' @ ' ) ;
2014-07-18 22:05:07 +05:00
if ( p ) * p = ' \0 ' ;
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , " origination_callee_id_number " , trimmed_dest ) ;
free ( trimmed_dest ) ;
}
2014-06-11 12:48:46 -05:00
cause = SWITCH_CAUSE_USER_NOT_REGISTERED ;
if ( dial_str ) {
switch_originate_flag_t myflags = SOF_NONE ;
if ( ( flags & SOF_NO_LIMITS ) ) {
myflags | = SOF_NO_LIMITS ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ( flags & SOF_FORKED_DIAL ) ) {
myflags | = SOF_NOBLOCK ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( switch_ivr_originate ( session , new_session , & cause , dial_str , 0 , NULL ,
FS-11346: [core] add api to pass pre-parsed values instead of dial strings to switch_ivr_originate
SWITCH_DECLARE(switch_status_t) switch_dial_handle_create(switch_dial_handle_t **handle);
SWITCH_DECLARE(void) switch_dial_handle_destroy(switch_dial_handle_t **handle);
SWITCH_DECLARE(void) switch_dial_handle_add_leg_list(switch_dial_handle_t *handle, switch_dial_leg_list_t **leg_listP);
SWITCH_DECLARE(void) switch_dial_leg_list_add_leg(switch_dial_leg_list_t *parent, const char *dial_string, switch_dial_leg_t **legP);
SWITCH_DECLARE(void) switch_dial_handle_add_global_var(switch_dial_handle_t *handle, const char *var, const char *val);
SWITCH_DECLARE(void) switch_dial_handle_add_global_var_printf(switch_dial_handle_t *handle, const char *var, const char *fmt, ...);
SWITCH_DECLARE(switch_status_t) switch_dial_handle_add_leg_var(switch_dial_leg_t *leg, const char *var, const char *val);
SWITCH_DECLARE(switch_status_t) switch_dial_handle_add_leg_var_printf(switch_dial_leg_t *leg, const char *var, const char *fmt, ...);
SWITCH_DECLARE(int) switch_dial_handle_get_peers(switch_dial_handle_t *handle, int idx, char **array, int max);
SWITCH_DECLARE(int) switch_dial_handle_get_vars(switch_dial_handle_t *handle, int idx, switch_event_t **array, int max);
SWITCH_DECLARE(switch_event_t *) switch_dial_handle_get_global_vars(switch_dial_handle_t *handle);
SWITCH_DECLARE(switch_event_t *) switch_dial_leg_get_vars(switch_dial_leg_t *leg);
SWITCH_DECLARE(int) switch_dial_handle_get_total(switch_dial_handle_t *handle);
SWITCH_DECLARE(void) switch_ivr_orig_and_bridge(switch_core_session_t *session, const char *data, switch_dial_handle_t *dh);
add switch_dial_handle_t *dh to end of args for switch_ivr_originate
2018-08-16 00:40:30 +00:00
NULL , NULL , outbound_profile , var_event , myflags , cancel_cause , NULL ) = = SWITCH_STATUS_SUCCESS ) {
2014-06-11 12:48:46 -05:00
switch_core_session_rwunlock ( * new_session ) ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
free ( dial_str ) ;
}
2021-04-06 21:31:44 +03:00
goto end ;
2014-07-18 22:05:07 +05:00
} else {
const char * dialed_user = switch_event_get_header ( var_event , " dialed_user " ) ;
const char * dialed_domain = switch_event_get_header ( var_event , " dialed_domain " ) ;
2017-01-06 02:10:15 -05:00
2014-07-18 22:05:07 +05:00
if ( dialed_user ) {
if ( dialed_domain ) {
switch_event_add_header ( var_event , SWITCH_STACK_BOTTOM , " verto_orig_dest " , " %s@%s " , dialed_user , dialed_domain ) ;
} else {
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , " verto_orig_dest " , dialed_user ) ;
}
if ( zstr ( switch_event_get_header ( var_event , " origination_callee_id_number " ) ) ) {
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , " origination_callee_id_number " , dialed_user ) ;
outbound_profile - > callee_id_number = switch_sanitize_number ( switch_core_strdup ( outbound_profile - > pool , dialed_user ) ) ;
}
}
2014-06-11 12:48:46 -05:00
}
if ( ( cause = switch_core_session_outgoing_channel ( session , var_event , " rtc " ,
outbound_profile , new_session , NULL , SOF_NONE , cancel_cause ) ) = = SWITCH_CAUSE_SUCCESS ) {
switch_channel_t * channel = switch_core_session_get_channel ( * new_session ) ;
char * jsock_uuid_str = outbound_profile - > destination_number + 2 ;
switch_caller_profile_t * caller_profile ;
verto_pvt_t * tech_pvt = NULL ;
char name [ 512 ] ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
tech_pvt = switch_core_session_alloc ( * new_session , sizeof ( * tech_pvt ) ) ;
2016-07-10 22:25:14 -05:00
tech_pvt - > pool = switch_core_session_get_pool ( * new_session ) ;
2014-06-11 12:48:46 -05:00
tech_pvt - > session = * new_session ;
tech_pvt - > channel = channel ;
tech_pvt - > jsock_uuid = switch_core_session_strdup ( * new_session , jsock_uuid_str ) ;
2016-07-10 22:25:14 -05:00
2014-06-11 12:48:46 -05:00
switch_core_session_set_private_class ( * new_session , tech_pvt , SWITCH_PVT_SECONDARY ) ;
2016-07-10 22:25:14 -05:00
2014-06-11 12:48:46 -05:00
if ( session ) {
switch_channel_t * ochannel = switch_core_session_get_channel ( session ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( switch_true ( switch_channel_get_variable ( ochannel , SWITCH_BYPASS_MEDIA_VARIABLE ) ) ) {
switch_channel_set_flag ( channel , CF_PROXY_MODE ) ;
switch_channel_set_flag ( ochannel , CF_PROXY_MODE ) ;
switch_channel_set_cap ( channel , CC_BYPASS_MEDIA ) ;
}
}
tech_pvt - > call_id = switch_core_session_strdup ( * new_session , switch_core_session_get_uuid ( * new_session ) ) ;
if ( ( tech_pvt - > smh = switch_core_session_get_media_handle ( * new_session ) ) ) {
tech_pvt - > mparams = switch_core_media_get_mparams ( tech_pvt - > smh ) ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_snprintf ( name , sizeof ( name ) , " verto.rtc/%s " , tech_pvt - > jsock_uuid ) ;
switch_channel_set_name ( channel , name ) ;
switch_channel_set_variable ( channel , " jsock_uuid_str " , tech_pvt - > jsock_uuid ) ;
switch_channel_set_variable ( channel , " event_channel_cookie " , tech_pvt - > jsock_uuid ) ;
2014-07-12 03:27:03 +05:00
2014-06-11 12:48:46 -05:00
if ( ( caller_profile = switch_caller_profile_dup ( switch_core_session_get_pool ( * new_session ) , outbound_profile ) ) ) {
2017-01-06 02:10:15 -05:00
switch_channel_set_caller_profile ( channel , caller_profile ) ;
}
2014-06-11 12:48:46 -05:00
switch_channel_add_state_handler ( channel , & verto_state_handlers ) ;
switch_core_event_hook_add_receive_message ( * new_session , messagehook ) ;
switch_channel_set_state ( channel , CS_INIT ) ;
2018-01-12 00:40:50 -06:00
//track_pvt(tech_pvt);
2014-06-11 12:48:46 -05:00
}
end :
2015-09-23 10:35:45 -05:00
if ( cause ! = SWITCH_CAUSE_SUCCESS ) {
UNPROTECT_INTERFACE ( verto_endpoint_interface ) ;
}
2014-06-11 12:48:46 -05:00
switch_safe_free ( dest ) ;
return cause ;
}
2019-05-16 15:25:10 +01:00
void verto_broadcast ( const char * event_channel , cJSON * json , const char * key , switch_event_channel_id_t id , void * user_data )
2014-06-11 12:48:46 -05:00
{
2017-02-09 17:23:30 -06:00
if ( verto_globals . debug > 9 ) {
2014-06-11 12:48:46 -05:00
char * json_text ;
2021-05-12 04:09:54 +00:00
if ( ( json_text = cJSON_PrintUnformatted ( json ) ) ) {
2020-04-01 00:31:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , verto_globals . debug_level , " EVENT BROADCAST %s %s \n " , event_channel , json_text ) ;
2014-06-11 12:48:46 -05:00
free ( json_text ) ;
}
}
jsock_send_event ( json ) ;
}
static int verto_send_chat ( const char * uid , const char * call_id , cJSON * msg )
{
jsock_t * jsock ;
verto_profile_t * profile ;
int hits = 0 ;
int done = 0 ;
if ( ! strchr ( uid , ' @ ' ) ) {
return 0 ;
}
if ( call_id ) {
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( call_id ) ) ) {
verto_pvt_t * tech_pvt = switch_core_session_get_private_class ( session , SWITCH_PVT_SECONDARY ) ;
if ( ( jsock = get_jsock ( tech_pvt - > jsock_uuid ) ) ) {
2014-07-24 02:44:34 -04:00
jsock_queue_event ( jsock , & msg , SWITCH_FALSE ) ;
2014-07-18 01:03:57 +05:00
//if (ws_write_json(jsock, &msg, SWITCH_FALSE) <= 0) {
// switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
//}
2014-06-11 12:48:46 -05:00
switch_thread_rwlock_unlock ( jsock - > rwlock ) ;
done = 1 ;
}
switch_core_session_rwunlock ( session ) ;
}
}
if ( done ) {
return 1 ;
}
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . mutex ) ;
for ( profile = verto_globals . profile_head ; profile ; profile = profile - > next ) {
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_mutex_lock ( profile - > mutex ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
for ( jsock = profile - > jsock_head ; jsock ; jsock = jsock - > next ) {
2014-07-24 02:44:34 -04:00
if ( jsock - > ready & & ! zstr ( jsock - > uid ) & & ! strcmp ( uid , jsock - > uid ) ) {
jsock_queue_event ( jsock , & msg , SWITCH_FALSE ) ;
2014-06-11 12:48:46 -05:00
hits + + ;
}
}
switch_mutex_unlock ( profile - > mutex ) ;
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . mutex ) ;
2014-06-11 12:48:46 -05:00
return hits ;
}
static switch_status_t chat_send ( switch_event_t * message_event )
{
switch_status_t status = SWITCH_STATUS_SUCCESS ;
const char * to = switch_event_get_header ( message_event , " to " ) ;
const char * from = switch_event_get_header ( message_event , " from " ) ;
const char * body = switch_event_get_body ( message_event ) ;
2017-01-06 02:10:15 -05:00
const char * call_id = switch_event_get_header ( message_event , " call_id " ) ;
2014-06-11 12:48:46 -05:00
2014-07-24 22:58:12 +05:00
//DUMP_EVENT(message_event);
2014-06-11 12:48:46 -05:00
if ( ! zstr ( to ) & & ! zstr ( body ) & & ! zstr ( from ) ) {
cJSON * obj = NULL , * msg = NULL , * params = NULL ;
2014-07-24 22:58:12 +05:00
switch_event_header_t * eh ;
2014-06-11 12:48:46 -05:00
obj = jrpc_new_req ( " verto.info " , call_id , & params ) ;
msg = json_add_child_obj ( params , " msg " , NULL ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
cJSON_AddItemToObject ( msg , " from " , cJSON_CreateString ( from ) ) ;
cJSON_AddItemToObject ( msg , " to " , cJSON_CreateString ( to ) ) ;
cJSON_AddItemToObject ( msg , " body " , cJSON_CreateString ( body ) ) ;
2014-07-24 02:44:34 -04:00
2014-07-24 22:58:12 +05:00
for ( eh = message_event - > headers ; eh ; eh = eh - > next ) {
2019-07-12 19:59:40 +04:00
if ( ! strncasecmp ( eh - > name , " from_ " , 5 ) | | ! strncasecmp ( eh - > name , " to_ " , 3 ) ) {
2017-01-06 02:10:15 -05:00
cJSON_AddItemToObject ( msg , eh - > name , cJSON_CreateString ( eh - > value ) ) ;
2014-07-24 22:58:12 +05:00
}
}
2014-06-11 12:48:46 -05:00
verto_send_chat ( to , call_id , obj ) ;
cJSON_Delete ( obj ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " INVALID EVENT \n " ) ;
2014-07-24 22:58:12 +05:00
DUMP_EVENT ( message_event ) ;
2014-06-11 12:48:46 -05:00
status = SWITCH_STATUS_FALSE ;
}
return status ;
}
static switch_cache_db_handle_t * json_get_db_handle ( void )
{
switch_cache_db_handle_t * dbh = NULL ;
const char * dsn ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! ( dsn = switch_core_get_variable ( " json_db_handle " ) ) ) {
dsn = " json " ;
}
if ( switch_cache_db_get_db_handle_dsn ( & dbh , dsn ) ! = SWITCH_STATUS_SUCCESS ) {
dbh = NULL ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
return dbh ;
}
static int jcallback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
char * * data = ( char * * ) pArg ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( argv [ 0 ] & & ! * data ) {
* data = strdup ( argv [ 0 ] ) ;
}
return 0 ;
}
static cJSON * json_retrieve ( const char * name , switch_mutex_t * mutex )
{
char * sql , * errmsg ;
switch_cache_db_handle_t * dbh ;
char * ascii = NULL ;
cJSON * json = NULL ;
if ( ! check_name ( name ) ) {
return NULL ;
}
sql = switch_mprintf ( " select data from json_store where name='%q' " , name ) ;
dbh = json_get_db_handle ( ) ;
if ( mutex ) switch_mutex_lock ( mutex ) ;
switch_cache_db_execute_sql_callback ( dbh , sql , jcallback , & ascii , & errmsg ) ;
switch_cache_db_release_db_handle ( & dbh ) ;
if ( errmsg ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " SQL ERR: [%s] %s \n " , sql , errmsg ) ;
free ( errmsg ) ;
} else {
if ( ascii ) {
json = cJSON_Parse ( ascii ) ;
}
}
if ( mutex ) switch_mutex_unlock ( mutex ) ;
switch_safe_free ( ascii ) ;
return json ;
}
static switch_bool_t json_commit ( cJSON * json , const char * name , switch_mutex_t * mutex )
{
2014-06-11 17:11:47 -05:00
char * ascii ;
2014-06-11 12:48:46 -05:00
char * sql ;
char del_sql [ 128 ] = " " ;
switch_cache_db_handle_t * dbh ;
char * err ;
if ( ! check_name ( name ) ) {
return SWITCH_FALSE ;
}
if ( ! ( ascii = cJSON_PrintUnformatted ( json ) ) ) {
return SWITCH_FALSE ;
}
sql = switch_mprintf ( " insert into json_store (name,data) values('%q','%q') " , name , ascii ) ;
2014-12-22 15:09:50 -06:00
switch_snprintfv ( del_sql , sizeof ( del_sql ) , " delete from json_store where name='%q' " , name ) ;
2014-06-11 12:48:46 -05:00
dbh = json_get_db_handle ( ) ;
if ( mutex ) switch_mutex_lock ( mutex ) ;
switch_cache_db_execute_sql ( dbh , del_sql , & err ) ;
if ( err ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " sql err [%s] \n " , err ) ;
free ( err ) ;
} else {
switch_cache_db_execute_sql ( dbh , sql , & err ) ;
if ( err ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " sql err [%s] \n " , err ) ;
free ( err ) ;
}
}
if ( mutex ) switch_mutex_unlock ( mutex ) ;
switch_safe_free ( sql ) ;
switch_safe_free ( ascii ) ;
switch_cache_db_release_db_handle ( & dbh ) ;
return SWITCH_TRUE ;
}
static switch_status_t json_hanguphook ( switch_core_session_t * session )
{
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
switch_channel_state_t state = switch_channel_get_state ( channel ) ;
json_store_t * session_store = NULL ;
char * ascii = NULL ;
if ( state = = CS_HANGUP ) {
if ( ( session_store = ( json_store_t * ) switch_channel_get_private ( channel , " _json_store_ " ) ) ) {
if ( ( ascii = cJSON_PrintUnformatted ( session_store - > JSON_STORE ) ) ) {
switch_channel_set_variable ( channel , " json_store_data " , ascii ) ;
free ( ascii ) ;
}
cJSON_Delete ( session_store - > JSON_STORE ) ;
session_store - > JSON_STORE = NULL ;
switch_channel_set_private ( channel , " _json_store_ " , NULL ) ;
}
switch_core_event_hook_remove_state_change ( session , json_hanguphook ) ;
}
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_STANDARD_JSON_API ( json_store_function )
{
2014-12-22 15:09:50 -06:00
cJSON * JSON_STORE = NULL , * reply = NULL , * data = cJSON_GetObjectItem ( json , " data " ) ;
2014-06-11 12:48:46 -05:00
switch_status_t status = SWITCH_STATUS_FALSE ;
const char * cmd_attr = cJSON_GetObjectCstr ( data , " cmd " ) ;
const char * uuid = cJSON_GetObjectCstr ( data , " uuid " ) ;
const char * error = NULL , * message = NULL ;
store_cmd_t cmd ;
const char * key = cJSON_GetObjectCstr ( data , " key " ) ;
const char * verbose = cJSON_GetObjectCstr ( data , " verbose " ) ;
const char * commit = cJSON_GetObjectCstr ( data , " commit " ) ;
const char * file = cJSON_GetObjectCstr ( data , " file " ) ;
const char * storename = cJSON_GetObjectCstr ( data , " storeName " ) ;
cJSON * obj , * * use_store = NULL ;
switch_core_session_t * tsession = NULL ;
switch_channel_t * tchannel = NULL ;
json_store_t * session_store = NULL ;
reply = cJSON_CreateObject ( ) ;
if ( uuid ) {
if ( ( tsession = switch_core_session_locate ( uuid ) ) ) {
tchannel = switch_core_session_get_channel ( tsession ) ;
} else {
error = " Invalid INPUT, Missing UUID " ;
goto end ;
}
} else {
if ( zstr ( storename ) ) {
storename = " global " ;
}
}
if ( zstr ( cmd_attr ) ) {
error = " INVALID INPUT, Command not supplied " ;
goto end ;
}
if ( ! strcasecmp ( cmd_attr , " add " ) ) {
cmd = CMD_ADD ;
} else if ( ! strcasecmp ( cmd_attr , " del " ) ) {
cmd = CMD_DEL ;
} else if ( ! strcasecmp ( cmd_attr , " dump " ) ) {
cmd = CMD_DUMP ;
} else if ( ! strcasecmp ( cmd_attr , " commit " ) ) {
cmd = CMD_COMMIT ;
} else if ( ! strcasecmp ( cmd_attr , " retrieve " ) ) {
cmd = CMD_RETRIEVE ;
} else {
error = " INVALID INPUT, Unknown Command " ;
goto end ;
}
if ( cmd = = CMD_ADD ) {
if ( zstr ( key ) ) {
error = " INVALID INPUT, No key supplied " ;
goto end ;
}
}
if ( cmd = = CMD_RETRIEVE | | cmd = = CMD_COMMIT ) {
if ( zstr ( file ) ) {
error = " INVALID INPUT, No file specified " ;
goto end ;
}
}
switch_mutex_lock ( json_GLOBALS . store_mutex ) ;
if ( tsession ) {
if ( ! ( session_store = ( json_store_t * ) switch_channel_get_private ( tchannel , " _json_store_ " ) ) ) {
session_store = switch_core_session_alloc ( tsession , sizeof ( * session_store ) ) ;
switch_mutex_init ( & session_store - > mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( tsession ) ) ;
session_store - > JSON_STORE = cJSON_CreateObject ( ) ;
switch_channel_set_private ( tchannel , " _json_store_ " , session_store ) ;
switch_core_event_hook_add_state_change ( tsession , json_hanguphook ) ;
}
use_store = & session_store - > JSON_STORE ;
switch_mutex_lock ( session_store - > mutex ) ;
switch_mutex_unlock ( json_GLOBALS . store_mutex ) ;
} else {
JSON_STORE = switch_core_hash_find ( json_GLOBALS . store_hash , storename ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! JSON_STORE ) {
JSON_STORE = cJSON_CreateObject ( ) ;
switch_core_hash_insert ( json_GLOBALS . store_hash , storename , JSON_STORE ) ;
}
use_store = & JSON_STORE ;
}
switch ( cmd ) {
case CMD_RETRIEVE :
obj = json_retrieve ( file , NULL ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! obj ) {
error = " CANNOT LOAD DATA " ;
if ( session_store ) {
switch_mutex_unlock ( session_store - > mutex ) ;
} else {
switch_mutex_unlock ( json_GLOBALS . store_mutex ) ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
goto end ;
}
cJSON_Delete ( * use_store ) ;
* use_store = obj ;
message = " Store Loaded " ;
break ;
case CMD_ADD :
if ( ! ( obj = cJSON_GetObjectItem ( data , key ) ) ) {
error = " INVALID INPUT " ;
if ( session_store ) {
switch_mutex_unlock ( session_store - > mutex ) ;
} else {
switch_mutex_unlock ( json_GLOBALS . store_mutex ) ;
}
goto end ;
}
cJSON_DeleteItemFromObject ( * use_store , key ) ;
obj = cJSON_Duplicate ( obj , 1 ) ;
cJSON_AddItemToObject ( * use_store , key , obj ) ;
message = " Item Added " ;
break ;
case CMD_DEL :
if ( ! key ) {
cJSON_Delete ( * use_store ) ;
* use_store = cJSON_CreateObject ( ) ;
message = " Store Deleted " ;
} else {
cJSON_DeleteItemFromObject ( * use_store , key ) ;
message = " Item Deleted " ;
}
break ;
default :
break ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( switch_true ( verbose ) | | cmd = = CMD_DUMP ) {
cJSON * dump ;
if ( key ) {
dump = cJSON_GetObjectItem ( * use_store , key ) ;
} else {
dump = * use_store ;
}
if ( dump ) {
dump = cJSON_Duplicate ( dump , 1 ) ;
cJSON_AddItemToObject ( reply , " data " , dump ) ;
message = " Data Dumped " ;
} else {
error = " Key not found " ;
}
}
if ( session_store ) {
switch_mutex_unlock ( session_store - > mutex ) ;
} else {
switch_mutex_unlock ( json_GLOBALS . store_mutex ) ;
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( cmd = = CMD_COMMIT | | commit ) {
switch_bool_t ok ;
if ( commit & & zstr ( file ) ) {
file = commit ;
}
if ( session_store ) {
ok = json_commit ( session_store - > JSON_STORE , file , session_store - > mutex ) ;
} else {
ok = json_commit ( JSON_STORE , file , json_GLOBALS . store_mutex ) ;
}
cJSON_AddItemToObject ( reply , " commitStatus " , cJSON_CreateString ( ok ? " success " : " fail " ) ) ;
if ( ! message ) {
message = " Message Comitted " ;
}
status = SWITCH_STATUS_SUCCESS ;
}
end :
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
if ( ! zstr ( error ) ) {
cJSON_AddItemToObject ( reply , " errorMessage " , cJSON_CreateString ( error ) ) ;
}
if ( ! zstr ( message ) ) {
cJSON_AddItemToObject ( reply , " message " , cJSON_CreateString ( message ) ) ;
status = SWITCH_STATUS_SUCCESS ;
}
* json_reply = reply ;
if ( tsession ) {
switch_core_session_rwunlock ( tsession ) ;
}
return status ;
}
# define add_it(_name, _ename) if ((tmp = switch_event_get_header(event, _ename))) { cJSON_AddItemToObject(data, _name, cJSON_CreateString(tmp));}
static void presence_event_handler ( switch_event_t * event )
{
cJSON * msg = NULL , * data = NULL ;
const char * tmp ;
switch_event_header_t * hp ;
char * event_channel ;
const char * presence_id = switch_event_get_header ( event , " channel-presence-id " ) ;
2017-02-09 17:23:30 -06:00
if ( ! verto_globals . running ) {
2014-07-18 01:03:57 +05:00
return ;
}
2017-02-09 17:23:30 -06:00
if ( ! verto_globals . enable_presence | | zstr ( presence_id ) ) {
2014-06-11 12:48:46 -05:00
return ;
}
msg = cJSON_CreateObject ( ) ;
data = json_add_child_obj ( msg , " data " , NULL ) ;
event_channel = switch_mprintf ( " presence.%s " , presence_id ) ;
cJSON_AddItemToObject ( msg , " eventChannel " , cJSON_CreateString ( event_channel ) ) ;
add_it ( " channelCallState " , " channel-call-state " ) ;
add_it ( " originalChannelCallState " , " original-channel-call-state " ) ;
add_it ( " channelState " , " channel-state " ) ;
add_it ( " callerUserName " , " caller-username " ) ;
add_it ( " callerIDName " , " caller-caller-id-name " ) ;
add_it ( " callerIDNumber " , " caller-caller-id-number " ) ;
add_it ( " calleeIDName " , " caller-callee-id-name " ) ;
add_it ( " calleeIDNumber " , " caller-callee-id-number " ) ;
add_it ( " channelUUID " , " unique-id " ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
add_it ( " presenceCallDirection " , " presence-call-direction " ) ;
add_it ( " channelPresenceID " , " channel-presence-id " ) ;
add_it ( " channelPresenceData " , " channel-presence-data " ) ;
for ( hp = event - > headers ; hp ; hp = hp - > next ) {
if ( ! strncasecmp ( hp - > name , " PD- " , 3 ) ) {
add_it ( hp - > name , hp - > name ) ;
}
}
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
switch_event_channel_broadcast ( event_channel , & msg , __FILE__ , NO_EVENT_CHANNEL_ID ) ;
free ( event_channel ) ;
}
2014-07-18 01:03:57 +05:00
static void event_handler ( switch_event_t * event )
{
cJSON * msg = NULL , * data = NULL ;
char * event_channel ;
2017-02-09 17:23:30 -06:00
if ( ! verto_globals . enable_fs_events ) {
2014-07-18 01:03:57 +05:00
return ;
}
switch_event_serialize_json_obj ( event , & data ) ;
msg = cJSON_CreateObject ( ) ;
if ( event - > event_id = = SWITCH_EVENT_CUSTOM ) {
const char * subclass = switch_event_get_header ( event , " Event-Subclass " ) ;
event_channel = switch_mprintf ( " FSevent.%s::%s " , switch_event_name ( event - > event_id ) , subclass ) ;
switch_tolower_max ( event_channel + 8 ) ;
} else {
event_channel = switch_mprintf ( " FSevent.%s " , switch_event_name ( event - > event_id ) ) ;
switch_tolower_max ( event_channel + 8 ) ;
}
2017-01-06 02:10:15 -05:00
2014-07-18 01:03:57 +05:00
cJSON_AddItemToObject ( msg , " eventChannel " , cJSON_CreateString ( event_channel ) ) ;
cJSON_AddItemToObject ( msg , " data " , data ) ;
/* comment broadcasting globally and change to only within the module cos FS events are heavy */
//switch_event_channel_broadcast(event_channel, &msg, __FILE__, NO_EVENT_CHANNEL_ID);
2019-05-16 15:25:10 +01:00
verto_broadcast ( event_channel , msg , __FILE__ , NO_EVENT_CHANNEL_ID , NULL ) ; cJSON_Delete ( msg ) ;
2014-07-18 01:03:57 +05:00
free ( event_channel ) ;
}
2014-06-11 12:48:46 -05:00
2020-03-25 03:49:19 +04:00
static void mod_verto_ks_logger ( const char * file , const char * func , int line , int level , const char * fmt , . . . )
{
char fmt_buf [ 32768 ] ;
va_list ap ;
size_t len ;
va_start ( ap , fmt ) ;
len = snprintf ( fmt_buf , sizeof ( fmt_buf ) , " %s \n " , fmt ) ; // add return that is missing
if ( level = = SWITCH_LOG_DEBUG ) level = SWITCH_LOG_DEBUG1 ;
if ( len < sizeof ( fmt_buf ) ) {
switch_log_vprintf ( SWITCH_CHANNEL_ID_LOG , file , func , line , NULL , level , fmt_buf , ap ) ;
} else {
switch_log_vprintf ( SWITCH_CHANNEL_ID_LOG , file , func , line , NULL , level , fmt , ap ) ;
}
va_end ( ap ) ;
}
2023-07-08 06:29:23 -05:00
static void verto_event_free_subclass ( void )
2022-01-25 16:27:49 +02:00
{
switch_event_free_subclass ( MY_EVENT_LOGIN ) ;
switch_event_free_subclass ( MY_EVENT_CLIENT_DISCONNECT ) ;
switch_event_free_subclass ( MY_EVENT_CLIENT_CONNECT ) ;
}
2023-07-08 06:29:23 -05:00
static void verto_destroy_globals_hash_tables ( void )
2022-01-25 16:27:49 +02:00
{
if ( verto_globals . method_hash ) {
switch_core_hash_destroy ( & verto_globals . method_hash ) ;
}
if ( verto_globals . event_channel_hash ) {
switch_core_hash_destroy ( & verto_globals . event_channel_hash ) ;
}
if ( verto_globals . jsock_hash ) {
switch_core_hash_destroy ( & verto_globals . jsock_hash ) ;
}
}
2014-06-11 12:48:46 -05:00
/* Macro expands to: switch_status_t mod_verto_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
SWITCH_MODULE_LOAD_FUNCTION ( mod_verto_load )
{
switch_api_interface_t * api_interface = NULL ;
switch_chat_interface_t * chat_interface = NULL ;
switch_json_api_interface_t * json_api_interface = NULL ;
int r ;
switch_cache_db_handle_t * dbh ;
//switch_application_interface_t *app_interface = NULL;
2020-03-25 03:49:19 +04:00
ks_ssl_init_skip ( KS_TRUE ) ;
ks_init ( ) ;
2015-09-21 18:00:14 -05:00
2023-01-16 18:52:26 +03:00
# if defined(KS_VERSION_NUM) && KS_VERSION_NUM < 20000
kws_set_global_payload_size_max ( 1000000 ) ;
# endif
2015-09-21 18:00:14 -05:00
if ( switch_event_reserve_subclass ( MY_EVENT_LOGIN ) ! = SWITCH_STATUS_SUCCESS ) {
2022-01-25 16:27:49 +02:00
ks_shutdown ( ) ;
2015-09-21 18:00:14 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't register subclass %s! \n " , MY_EVENT_LOGIN ) ;
return SWITCH_STATUS_TERM ;
}
2017-01-06 02:10:15 -05:00
2015-09-21 18:00:14 -05:00
if ( switch_event_reserve_subclass ( MY_EVENT_CLIENT_DISCONNECT ) ! = SWITCH_STATUS_SUCCESS ) {
2022-01-25 16:27:49 +02:00
switch_event_free_subclass ( MY_EVENT_LOGIN ) ;
ks_shutdown ( ) ;
2015-09-21 18:00:14 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't register subclass %s! \n " , MY_EVENT_CLIENT_DISCONNECT ) ;
return SWITCH_STATUS_TERM ;
}
2017-01-06 02:10:15 -05:00
2015-09-21 18:00:14 -05:00
if ( switch_event_reserve_subclass ( MY_EVENT_CLIENT_CONNECT ) ! = SWITCH_STATUS_SUCCESS ) {
2022-01-25 16:27:49 +02:00
switch_event_free_subclass ( MY_EVENT_LOGIN ) ;
switch_event_free_subclass ( MY_EVENT_CLIENT_DISCONNECT ) ;
ks_shutdown ( ) ;
2015-09-21 18:00:14 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't register subclass %s! \n " , MY_EVENT_CLIENT_CONNECT ) ;
return SWITCH_STATUS_TERM ;
}
2017-01-06 02:10:15 -05:00
2017-02-09 17:23:30 -06:00
memset ( & verto_globals , 0 , sizeof ( verto_globals ) ) ;
verto_globals . pool = pool ;
2014-10-18 09:53:57 +02:00
# ifndef WIN32
2017-02-09 17:23:30 -06:00
verto_globals . ready = SIGUSR1 ;
2014-10-18 09:53:57 +02:00
# endif
2017-02-09 17:23:30 -06:00
verto_globals . enable_presence = SWITCH_TRUE ;
verto_globals . enable_fs_events = SWITCH_FALSE ;
2020-04-01 00:31:23 +00:00
verto_globals . debug_level = SWITCH_LOG_INFO ;
2017-02-09 17:23:30 -06:00
switch_mutex_init ( & verto_globals . mutex , SWITCH_MUTEX_NESTED , verto_globals . pool ) ;
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
switch_mutex_init ( & verto_globals . method_mutex , SWITCH_MUTEX_NESTED , verto_globals . pool ) ;
switch_core_hash_init ( & verto_globals . method_hash ) ;
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_create ( & verto_globals . event_channel_rwlock , verto_globals . pool ) ;
switch_core_hash_init ( & verto_globals . event_channel_hash ) ;
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
switch_mutex_init ( & verto_globals . jsock_mutex , SWITCH_MUTEX_NESTED , verto_globals . pool ) ;
switch_core_hash_init ( & verto_globals . jsock_hash ) ;
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
switch_thread_rwlock_create ( & verto_globals . tech_rwlock , verto_globals . pool ) ;
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
switch_mutex_init ( & verto_globals . detach_mutex , SWITCH_MUTEX_NESTED , verto_globals . pool ) ;
switch_mutex_init ( & verto_globals . detach2_mutex , SWITCH_MUTEX_NESTED , verto_globals . pool ) ;
switch_thread_cond_create ( & verto_globals . detach_cond , verto_globals . pool ) ;
verto_globals . detach_timeout = 120 ;
2014-06-11 12:48:46 -05:00
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
memset ( & json_GLOBALS , 0 , sizeof ( json_GLOBALS ) ) ;
switch_mutex_init ( & json_GLOBALS . store_mutex , SWITCH_MUTEX_NESTED , pool ) ;
switch_core_hash_init ( & json_GLOBALS . store_hash ) ;
dbh = json_get_db_handle ( ) ;
switch_cache_db_test_reactive ( dbh , " select name from json_store where name='' " , " drop table json_store " , json_sql ) ;
switch_cache_db_release_db_handle ( & dbh ) ;
2019-05-16 15:25:10 +01:00
switch_event_channel_bind ( SWITCH_EVENT_CHANNEL_GLOBAL , verto_broadcast , & verto_globals . event_channel_id , NULL ) ;
2014-06-11 12:48:46 -05:00
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
r = init ( ) ;
2022-01-25 16:27:49 +02:00
if ( r ) {
switch_core_hash_destroy ( & json_GLOBALS . store_hash ) ;
verto_event_free_subclass ( ) ;
switch_event_channel_unbind ( NULL , verto_broadcast , NULL ) ;
verto_destroy_globals_hash_tables ( ) ;
ks_shutdown ( ) ;
return SWITCH_STATUS_TERM ;
}
2014-06-11 12:48:46 -05:00
2020-03-25 03:49:19 +04:00
if ( verto_globals . kslog_on = = SWITCH_TRUE ) {
ks_global_set_logger ( mod_verto_ks_logger ) ;
ks_log ( KS_LOG_INFO , " ks log registered in mod_verto \n " ) ;
}
2014-06-11 12:48:46 -05:00
jrpc_init ( ) ;
/* connect my internal structure to the blank pointer passed to me */
* module_interface = switch_loadable_module_create_module_interface ( pool , modname ) ;
SWITCH_ADD_API ( api_interface , " verto " , " Verto API " , verto_function , " syntax " ) ;
SWITCH_ADD_API ( api_interface , " verto_contact " , " Generate a verto endpoint dialstring " , verto_contact_function , " user@domain " ) ;
2014-07-31 23:04:10 +05:00
switch_console_set_complete ( " add verto help " ) ;
2020-04-01 00:31:23 +00:00
switch_console_set_complete ( " add verto debug " ) ;
2020-05-09 02:03:19 +00:00
switch_console_set_complete ( " add verto perm " ) ;
switch_console_set_complete ( " add verto noperm " ) ;
2020-04-01 00:31:23 +00:00
switch_console_set_complete ( " add verto debug-level " ) ;
2014-07-31 23:04:10 +05:00
switch_console_set_complete ( " add verto status " ) ;
switch_console_set_complete ( " add verto xmlstatus " ) ;
2014-06-11 12:48:46 -05:00
SWITCH_ADD_JSON_API ( json_api_interface , " store " , " JSON store " , json_store_function , " " ) ;
verto_endpoint_interface = ( switch_endpoint_interface_t * ) switch_loadable_module_create_interface ( * module_interface , SWITCH_ENDPOINT_INTERFACE ) ;
verto_endpoint_interface - > interface_name = EP_NAME ;
verto_endpoint_interface - > io_routines = & verto_io_routines ;
SWITCH_ADD_CHAT ( chat_interface , VERTO_CHAT_PROTO , chat_send ) ;
switch_core_register_secondary_recover_callback ( modname , verto_recover_callback ) ;
2017-02-09 17:23:30 -06:00
if ( verto_globals . enable_presence ) {
2014-07-18 01:03:57 +05:00
switch_event_bind ( modname , SWITCH_EVENT_CHANNEL_CALLSTATE , SWITCH_EVENT_SUBCLASS_ANY , presence_event_handler , NULL ) ;
}
2017-02-09 17:23:30 -06:00
if ( verto_globals . enable_fs_events ) {
2014-07-18 01:03:57 +05:00
if ( switch_event_bind ( modname , SWITCH_EVENT_ALL , SWITCH_EVENT_SUBCLASS_ANY , event_handler , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
2022-01-25 16:27:49 +02:00
verto_event_free_subclass ( ) ;
switch_event_channel_unbind ( NULL , verto_broadcast , NULL ) ;
switch_core_hash_destroy ( & json_GLOBALS . store_hash ) ;
verto_destroy_globals_hash_tables ( ) ;
ks_global_set_logger ( NULL ) ;
ks_shutdown ( ) ;
2014-07-18 01:03:57 +05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
return SWITCH_STATUS_GENERR ;
}
}
2014-06-11 12:48:46 -05:00
run_profiles ( ) ;
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS ;
}
/*
Called when the system shuts down
Macro expands to : switch_status_t mod_verto_shutdown ( ) */
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_verto_shutdown )
{
2015-09-21 18:00:14 -05:00
2022-01-25 16:27:49 +02:00
verto_event_free_subclass ( ) ;
2017-01-06 02:10:15 -05:00
2014-06-11 12:48:46 -05:00
json_cleanup ( ) ;
switch_core_hash_destroy ( & json_GLOBALS . store_hash ) ;
2019-05-16 15:25:10 +01:00
switch_event_channel_unbind ( NULL , verto_broadcast , NULL ) ;
2014-06-11 12:48:46 -05:00
switch_event_unbind_callback ( presence_event_handler ) ;
2014-07-18 01:03:57 +05:00
switch_event_unbind_callback ( event_handler ) ;
2014-06-11 12:48:46 -05:00
switch_core_unregister_secondary_recover_callback ( modname ) ;
do_shutdown ( ) ;
attach_wake ( ) ;
attach_wake ( ) ;
2022-01-25 16:27:49 +02:00
verto_destroy_globals_hash_tables ( ) ;
2014-06-11 12:48:46 -05:00
2020-03-25 03:49:19 +04:00
ks_global_set_logger ( NULL ) ;
ks_shutdown ( ) ;
2014-06-11 12:48:46 -05:00
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_MODULE_RUNTIME_FUNCTION ( mod_verto_runtime )
{
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . detach_mutex ) ;
2014-06-11 12:48:46 -05:00
2017-02-09 17:23:30 -06:00
while ( verto_globals . running ) {
if ( verto_globals . detached ) {
2014-06-11 12:48:46 -05:00
drop_detached ( ) ;
switch_yield ( 1000000 ) ;
} else {
2017-02-09 17:23:30 -06:00
switch_mutex_lock ( verto_globals . detach2_mutex ) ;
if ( verto_globals . running ) {
switch_thread_cond_wait ( verto_globals . detach_cond , verto_globals . detach_mutex ) ;
2014-06-11 12:48:46 -05:00
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . detach2_mutex ) ;
2014-06-11 12:48:46 -05:00
}
}
2017-02-09 17:23:30 -06:00
switch_mutex_unlock ( verto_globals . detach_mutex ) ;
2014-06-11 12:48:46 -05:00
return SWITCH_STATUS_TERM ;
}
/* For Emacs:
* Local Variables :
* mode : c
* indent - tabs - mode : t
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 noet
*/