2017-01-06 07:10:15 +00:00
/*
2006-07-22 21:49:52 +00:00
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2014-02-05 21:02:28 +00:00
* Copyright ( C ) 2005 - 2014 , Anthony Minessale II < anthm @ freeswitch . org >
2006-07-22 21:49:52 +00:00
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2006-07-22 21:49:52 +00:00
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
2017-01-06 07:10:15 +00:00
*
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2014-02-28 22:11:22 +00:00
* Seven Du < dujinfang @ gmail . com >
2006-07-22 21:49:52 +00:00
*
*
2008-10-06 23:05:55 +00:00
* mod_event_socket . c - - Socket Controlled Event Handler
2006-07-22 21:49:52 +00:00
*
*/
# include <switch.h>
# define CMD_BUFLEN 1024 * 1000
2014-01-23 16:26:49 +00:00
# define MAX_QUEUE_LEN 100000
2011-01-25 20:13:15 +00:00
# define MAX_MISSED 500
2007-06-13 17:06:10 +00:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_event_socket_load ) ;
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_event_socket_shutdown ) ;
SWITCH_MODULE_RUNTIME_FUNCTION ( mod_event_socket_runtime ) ;
SWITCH_MODULE_DEFINITION ( mod_event_socket , mod_event_socket_load , mod_event_socket_shutdown , mod_event_socket_runtime ) ;
2006-07-22 21:49:52 +00:00
static char * MARKER = " 1 " ;
typedef enum {
LFLAG_AUTHED = ( 1 < < 0 ) ,
LFLAG_RUNNING = ( 1 < < 1 ) ,
LFLAG_EVENTS = ( 1 < < 2 ) ,
2007-01-06 17:06:18 +00:00
LFLAG_LOG = ( 1 < < 3 ) ,
LFLAG_FULL = ( 1 < < 4 ) ,
LFLAG_MYEVENTS = ( 1 < < 5 ) ,
LFLAG_SESSION = ( 1 < < 6 ) ,
2008-10-23 17:31:22 +00:00
LFLAG_ASYNC = ( 1 < < 7 ) ,
2008-12-12 15:44:37 +00:00
LFLAG_STATEFUL = ( 1 < < 8 ) ,
2009-01-16 15:32:10 +00:00
LFLAG_OUTBOUND = ( 1 < < 9 ) ,
LFLAG_LINGER = ( 1 < < 10 ) ,
2009-04-30 22:45:46 +00:00
LFLAG_HANDLE_DISCO = ( 1 < < 11 ) ,
LFLAG_CONNECTED = ( 1 < < 12 ) ,
LFLAG_RESUME = ( 1 < < 13 ) ,
2010-01-05 19:47:49 +00:00
LFLAG_AUTH_EVENTS = ( 1 < < 14 ) ,
LFLAG_ALL_EVENTS_AUTHED = ( 1 < < 15 ) ,
LFLAG_ALLOW_LOG = ( 1 < < 16 )
2006-07-22 21:49:52 +00:00
} event_flag_t ;
typedef enum {
EVENT_FORMAT_PLAIN ,
2010-06-17 16:43:09 +00:00
EVENT_FORMAT_XML ,
EVENT_FORMAT_JSON
2006-07-22 21:49:52 +00:00
} event_format_t ;
struct listener {
switch_socket_t * sock ;
switch_queue_t * event_queue ;
switch_queue_t * log_queue ;
switch_memory_pool_t * pool ;
event_format_t format ;
switch_mutex_t * flag_mutex ;
2008-10-30 00:39:55 +00:00
switch_mutex_t * filter_mutex ;
2006-07-22 21:49:52 +00:00
uint32_t flags ;
switch_log_level_t level ;
2006-08-29 23:06:12 +00:00
char * ebuf ;
2007-03-29 22:31:56 +00:00
uint8_t event_list [ SWITCH_EVENT_ALL + 1 ] ;
2010-01-05 19:47:49 +00:00
uint8_t allowed_event_list [ SWITCH_EVENT_ALL + 1 ] ;
2006-07-22 21:49:52 +00:00
switch_hash_t * event_hash ;
2010-01-05 19:47:49 +00:00
switch_hash_t * allowed_event_hash ;
switch_hash_t * allowed_api_hash ;
2006-09-07 03:58:01 +00:00
switch_thread_rwlock_t * rwlock ;
2007-03-29 22:31:56 +00:00
switch_core_session_t * session ;
2008-01-25 23:09:33 +00:00
int lost_events ;
int lost_logs ;
2008-10-23 17:31:22 +00:00
time_t last_flush ;
2009-11-06 20:17:31 +00:00
time_t expire_time ;
2008-10-23 17:31:22 +00:00
uint32_t timeout ;
uint32_t id ;
2008-03-26 22:14:09 +00:00
switch_sockaddr_t * sa ;
char remote_ip [ 50 ] ;
switch_port_t remote_port ;
2008-10-30 00:39:55 +00:00
switch_event_t * filters ;
2011-12-08 18:25:52 +00:00
time_t linger_timeout ;
2006-07-22 21:49:52 +00:00
struct listener * next ;
2012-06-26 14:58:51 +00:00
switch_pollfd_t * pollfd ;
2006-07-22 21:49:52 +00:00
} ;
typedef struct listener listener_t ;
2008-11-07 14:48:49 +00:00
static struct {
2010-02-06 03:38:24 +00:00
switch_mutex_t * listener_mutex ;
2008-11-07 14:48:49 +00:00
switch_event_node_t * node ;
2009-05-02 00:58:51 +00:00
int debug ;
2008-11-07 14:48:49 +00:00
} globals ;
2006-07-22 21:49:52 +00:00
static struct {
switch_socket_t * sock ;
2006-08-29 20:27:43 +00:00
switch_mutex_t * sock_mutex ;
2006-07-22 21:49:52 +00:00
listener_t * listeners ;
uint8_t ready ;
} listen_list ;
2008-03-26 22:14:09 +00:00
# define MAX_ACL 100
2006-07-22 21:49:52 +00:00
static struct {
2007-07-24 21:26:04 +00:00
switch_mutex_t * mutex ;
2006-07-22 21:49:52 +00:00
char * ip ;
uint16_t port ;
char * password ;
2006-11-09 05:39:04 +00:00
int done ;
2007-07-24 21:26:04 +00:00
int threads ;
2008-03-26 22:14:09 +00:00
char * acl [ MAX_ACL ] ;
uint32_t acl_count ;
2008-10-23 17:31:22 +00:00
uint32_t id ;
2009-06-03 14:25:35 +00:00
int nat_map ;
2014-02-24 10:28:25 +00:00
int stop_on_bind_error ;
2006-07-22 21:49:52 +00:00
} prefs ;
2008-10-23 17:31:22 +00:00
2010-06-17 16:43:09 +00:00
static const char * format2str ( event_format_t format )
{
switch ( format ) {
case EVENT_FORMAT_PLAIN :
return " plain " ;
case EVENT_FORMAT_XML :
return " xml " ;
case EVENT_FORMAT_JSON :
return " json " ;
}
return " invalid " ;
}
2008-10-23 17:31:22 +00:00
static void remove_listener ( listener_t * listener ) ;
2011-01-25 20:13:15 +00:00
static void kill_listener ( listener_t * l , const char * message ) ;
2009-02-20 01:10:59 +00:00
static void kill_all_listeners ( void ) ;
2008-10-23 17:31:22 +00:00
static uint32_t next_id ( void )
{
uint32_t id ;
2008-11-07 14:48:49 +00:00
switch_mutex_lock ( globals . listener_mutex ) ;
2010-02-06 03:38:24 +00:00
id = + + prefs . id ;
switch_mutex_unlock ( globals . listener_mutex ) ;
2008-10-23 17:31:22 +00:00
return id ;
}
2007-10-17 14:59:17 +00:00
SWITCH_DECLARE_GLOBAL_STRING_FUNC ( set_pref_ip , prefs . ip ) ;
SWITCH_DECLARE_GLOBAL_STRING_FUNC ( set_pref_pass , prefs . password ) ;
2006-07-22 21:49:52 +00:00
2008-05-27 04:54:52 +00:00
static void * SWITCH_THREAD_FUNC listener_run ( switch_thread_t * thread , void * obj ) ;
static void launch_listener_thread ( listener_t * listener ) ;
2007-01-06 17:06:18 +00:00
2007-10-17 14:59:17 +00:00
static switch_status_t socket_logger ( const switch_log_node_t * node , switch_log_level_t level )
2006-07-22 21:49:52 +00:00
{
listener_t * l ;
2017-03-23 13:01:45 +00:00
switch_status_t qstatus ;
2008-11-07 14:48:49 +00:00
switch_mutex_lock ( globals . listener_mutex ) ;
2006-07-22 21:49:52 +00:00
for ( l = listen_list . listeners ; l ; l = l - > next ) {
if ( switch_test_flag ( l , LFLAG_LOG ) & & l - > level > = node - > level ) {
2010-02-06 03:38:24 +00:00
switch_log_node_t * dnode = switch_log_node_dup ( node ) ;
2017-03-23 13:01:45 +00:00
qstatus = switch_queue_trypush ( l - > log_queue , dnode ) ;
if ( qstatus = = SWITCH_STATUS_SUCCESS ) {
2008-12-20 14:56:08 +00:00
if ( l - > lost_logs ) {
int ll = l - > lost_logs ;
l - > lost_logs = 0 ;
2017-03-23 13:01:45 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Lost [%d] log lines! Log Queue size: [%u/%u] \n " , ll , switch_queue_size ( l - > log_queue ) , MAX_QUEUE_LEN ) ;
2008-01-25 23:09:33 +00:00
}
2006-07-22 21:49:52 +00:00
} else {
2017-03-23 13:01:45 +00:00
char errbuf [ 512 ] = { 0 } ;
unsigned int qsize = switch_queue_size ( l - > log_queue ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT ,
" Log enqueue ERROR [%d] | [%s] Queue size: [%u/%u] %s \n " ,
( int ) qstatus , switch_strerror ( qstatus , errbuf , sizeof ( errbuf ) ) , qsize , MAX_QUEUE_LEN , ( qsize = = MAX_QUEUE_LEN ) ? " Max queue size reached " : " " ) ;
2009-08-22 19:26:58 +00:00
switch_log_node_free ( & dnode ) ;
2010-07-24 06:03:21 +00:00
if ( + + l - > lost_logs > MAX_MISSED ) {
2017-03-23 13:01:45 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT ,
" Killing listener because of too many lost log lines. Lost [%d] Queue size [%u/%u]! \n " , l - > lost_logs , qsize , MAX_QUEUE_LEN ) ;
kill_listener ( l , " killed listener because of lost log lines \n " ) ;
2010-07-24 06:03:21 +00:00
}
2006-07-22 21:49:52 +00:00
}
}
}
2008-11-07 14:48:49 +00:00
switch_mutex_unlock ( globals . listener_mutex ) ;
2006-07-22 21:49:52 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-10-29 19:15:14 +00:00
static void flush_listener ( listener_t * listener , switch_bool_t flush_log , switch_bool_t flush_events )
{
void * pop ;
2016-04-10 16:22:00 +00:00
if ( flush_log & & listener - > log_queue ) {
2008-10-29 19:15:14 +00:00
while ( switch_queue_trypop ( listener - > log_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
2008-12-20 14:56:08 +00:00
switch_log_node_t * dnode = ( switch_log_node_t * ) pop ;
if ( dnode ) {
2009-08-22 19:26:58 +00:00
switch_log_node_free ( & dnode ) ;
2008-12-20 14:56:08 +00:00
}
2008-10-29 19:15:14 +00:00
}
}
2016-04-10 16:22:00 +00:00
if ( flush_events & & listener - > event_queue ) {
2008-10-29 19:15:14 +00:00
while ( switch_queue_trypop ( listener - > event_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_t * pevent = ( switch_event_t * ) pop ;
2010-02-06 03:38:24 +00:00
if ( ! pop )
continue ;
2008-10-29 19:15:14 +00:00
switch_event_destroy ( & pevent ) ;
}
}
}
2008-10-23 21:58:09 +00:00
2010-02-06 03:38:24 +00:00
static switch_status_t expire_listener ( listener_t * * listener )
2008-10-23 21:58:09 +00:00
{
2009-11-21 06:17:05 +00:00
listener_t * l ;
2009-11-06 20:17:31 +00:00
2010-02-06 03:38:24 +00:00
if ( ! listener | | ! * listener )
return SWITCH_STATUS_FALSE ;
2009-11-21 06:17:05 +00:00
l = * listener ;
if ( ! l - > expire_time ) {
l - > expire_time = switch_epoch_time_now ( NULL ) ;
2009-11-06 20:17:31 +00:00
}
2009-11-21 06:17:05 +00:00
if ( switch_thread_rwlock_trywrlock ( l - > rwlock ) ! = SWITCH_STATUS_SUCCESS ) {
2009-11-06 20:17:31 +00:00
return SWITCH_STATUS_FALSE ;
}
2009-11-21 06:17:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( l - > session ) , SWITCH_LOG_CRIT , " Stateful Listener %u has expired \n " , l - > id ) ;
2009-11-06 20:17:31 +00:00
2008-10-29 19:15:14 +00:00
flush_listener ( * listener , SWITCH_TRUE , SWITCH_TRUE ) ;
2009-11-21 06:17:05 +00:00
switch_core_hash_destroy ( & l - > event_hash ) ;
2010-01-05 19:47:49 +00:00
if ( l - > allowed_event_hash ) {
2010-02-06 03:38:24 +00:00
switch_core_hash_destroy ( & l - > allowed_event_hash ) ;
}
2010-01-05 19:47:49 +00:00
if ( l - > allowed_api_hash ) {
2010-02-06 03:38:24 +00:00
switch_core_hash_destroy ( & l - > allowed_api_hash ) ;
}
2010-01-05 19:47:49 +00:00
2009-11-21 06:17:05 +00:00
switch_mutex_lock ( l - > filter_mutex ) ;
if ( l - > filters ) {
switch_event_destroy ( & l - > filters ) ;
2008-10-30 00:39:55 +00:00
}
2009-11-21 06:17:05 +00:00
switch_mutex_unlock ( l - > filter_mutex ) ;
switch_thread_rwlock_unlock ( l - > rwlock ) ;
switch_core_destroy_memory_pool ( & l - > pool ) ;
2008-10-23 21:58:09 +00:00
* listener = NULL ;
2009-11-06 20:17:31 +00:00
return SWITCH_STATUS_SUCCESS ;
2008-10-23 21:58:09 +00:00
}
2006-07-22 21:49:52 +00:00
static void event_handler ( switch_event_t * event )
{
switch_event_t * clone = NULL ;
2009-11-06 20:17:31 +00:00
listener_t * l , * lp , * last = NULL ;
2009-11-21 06:17:05 +00:00
time_t now = switch_epoch_time_now ( NULL ) ;
2017-03-23 13:01:45 +00:00
switch_status_t qstatus ;
2006-07-22 21:49:52 +00:00
2007-12-16 03:01:50 +00:00
switch_assert ( event ! = NULL ) ;
2006-07-22 21:49:52 +00:00
if ( ! listen_list . ready ) {
return ;
}
2010-02-06 03:38:24 +00:00
2015-02-10 08:15:18 +00:00
switch_mutex_lock ( globals . listener_mutex ) ;
2008-10-23 21:58:09 +00:00
lp = listen_list . listeners ;
2010-02-06 03:38:24 +00:00
while ( lp ) {
2008-10-30 02:27:22 +00:00
int send = 0 ;
2009-11-06 20:17:31 +00:00
2008-10-23 21:58:09 +00:00
l = lp ;
lp = lp - > next ;
2009-11-21 06:17:05 +00:00
if ( switch_test_flag ( l , LFLAG_STATEFUL ) & & ( l - > expire_time | | ( l - > timeout & & now - l - > last_flush > l - > timeout ) ) ) {
2009-11-06 20:17:31 +00:00
if ( expire_listener ( & l ) = = SWITCH_STATUS_SUCCESS ) {
if ( last ) {
last - > next = lp ;
} else {
listen_list . listeners = lp ;
}
continue ;
2009-05-02 00:58:51 +00:00
}
2008-10-23 17:31:22 +00:00
}
2010-02-06 03:38:24 +00:00
2009-11-21 06:17:05 +00:00
if ( l - > expire_time | | ! switch_test_flag ( l , LFLAG_EVENTS ) ) {
last = l ;
continue ;
2010-02-06 03:38:24 +00:00
}
2009-11-21 06:17:05 +00:00
2007-06-08 15:17:43 +00:00
if ( l - > event_list [ SWITCH_EVENT_ALL ] ) {
2006-07-25 14:14:07 +00:00
send = 1 ;
2007-06-08 15:17:43 +00:00
} else if ( ( l - > event_list [ event - > event_id ] ) ) {
2008-07-01 23:41:09 +00:00
if ( event - > event_id ! = SWITCH_EVENT_CUSTOM | | ! event - > subclass_name | | ( switch_core_hash_find ( l - > event_hash , event - > subclass_name ) ) ) {
2007-03-29 22:31:56 +00:00
send = 1 ;
}
}
2010-02-06 03:38:24 +00:00
2011-03-07 16:35:32 +00:00
if ( send ) {
2008-10-30 00:39:55 +00:00
switch_mutex_lock ( l - > filter_mutex ) ;
2008-10-30 23:37:16 +00:00
2011-03-07 16:35:32 +00:00
if ( l - > filters & & l - > filters - > headers ) {
switch_event_header_t * hp ;
const char * hval ;
send = 0 ;
2017-01-06 07:10:15 +00:00
2011-03-07 16:35:32 +00:00
for ( hp = l - > filters - > headers ; hp ; hp = hp - > next ) {
if ( ( hval = switch_event_get_header ( event , hp - > name ) ) ) {
const char * comp_to = hp - > value ;
int pos = 1 , cmp = 0 ;
while ( comp_to & & * comp_to ) {
if ( * comp_to = = ' + ' ) {
pos = 1 ;
} else if ( * comp_to = = ' - ' ) {
pos = 0 ;
} else if ( * comp_to ! = ' ' ) {
break ;
}
comp_to + + ;
}
2008-10-30 23:37:16 +00:00
2011-03-07 16:35:32 +00:00
if ( send & & pos ) {
continue ;
}
2010-02-06 03:38:24 +00:00
2011-03-07 16:35:32 +00:00
if ( ! comp_to ) {
continue ;
}
2008-10-30 23:37:16 +00:00
2011-03-07 16:35:32 +00:00
if ( * hp - > value = = ' / ' ) {
switch_regex_t * re = NULL ;
int ovector [ 30 ] ;
cmp = ! ! switch_regex_perform ( hval , comp_to , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
switch_regex_safe_free ( re ) ;
2008-10-30 23:37:16 +00:00
} else {
2011-03-07 16:35:32 +00:00
cmp = ! strcasecmp ( hval , comp_to ) ;
}
if ( cmp ) {
if ( pos ) {
send = 1 ;
} else {
send = 0 ;
break ;
}
2008-10-30 00:39:55 +00:00
}
}
}
}
2011-03-17 17:36:27 +00:00
switch_mutex_unlock ( l - > filter_mutex ) ;
2008-10-30 00:39:55 +00:00
}
2010-02-06 03:38:24 +00:00
2007-03-29 22:31:56 +00:00
if ( send & & switch_test_flag ( l , LFLAG_MYEVENTS ) ) {
char * uuid = switch_event_get_header ( event , " unique-id " ) ;
2012-10-30 04:16:46 +00:00
if ( ! uuid | | ( l - > session & & strcmp ( uuid , switch_core_session_get_uuid ( l - > session ) ) ) ) {
2007-06-08 15:17:43 +00:00
send = 0 ;
2006-07-25 14:14:07 +00:00
}
2019-08-22 19:35:34 +00:00
if ( ! strcmp ( switch_core_session_get_uuid ( l - > session ) , switch_event_get_header_nil ( event , " Job-Owner-UUID " ) ) ) {
send = 1 ;
}
2006-07-25 14:14:07 +00:00
}
if ( send ) {
if ( switch_event_dup ( & clone , event ) = = SWITCH_STATUS_SUCCESS ) {
2017-03-23 13:01:45 +00:00
qstatus = switch_queue_trypush ( l - > event_queue , clone ) ;
if ( qstatus = = SWITCH_STATUS_SUCCESS ) {
2008-01-25 23:09:33 +00:00
if ( l - > lost_events ) {
int le = l - > lost_events ;
l - > lost_events = 0 ;
2017-03-23 13:01:45 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( l - > session ) , SWITCH_LOG_CRIT , " Lost [%d] events! Event Queue size: [%u/%u] \n " , le , switch_queue_size ( l - > event_queue ) , MAX_QUEUE_LEN ) ;
2008-01-25 23:09:33 +00:00
}
} else {
2017-03-23 13:01:45 +00:00
char errbuf [ 512 ] = { 0 } ;
unsigned int qsize = switch_queue_size ( l - > event_queue ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT ,
" Event enqueue ERROR [%d] | [%s] | Queue size: [%u/%u] %s \n " ,
( int ) qstatus , switch_strerror ( qstatus , errbuf , sizeof ( errbuf ) ) , qsize , MAX_QUEUE_LEN , ( qsize = = MAX_QUEUE_LEN ) ? " Max queue size reached " : " " ) ;
2010-07-24 06:03:21 +00:00
if ( + + l - > lost_events > MAX_MISSED ) {
2017-03-23 13:01:45 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Killing listener because of too many lost events. Lost [%d] Queue size[%u/%u] \n " , l - > lost_events , qsize , MAX_QUEUE_LEN ) ;
kill_listener ( l , " killed listener because of lost events \n " ) ;
2010-07-24 06:03:21 +00:00
}
2008-01-25 23:09:33 +00:00
switch_event_destroy ( & clone ) ;
}
2006-07-25 14:14:07 +00:00
} else {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( l - > session ) , SWITCH_LOG_ERROR , " Memory Error! \n " ) ;
2006-07-22 21:49:52 +00:00
}
}
2009-11-21 06:17:05 +00:00
last = l ;
2006-07-22 21:49:52 +00:00
}
2008-11-07 14:48:49 +00:00
switch_mutex_unlock ( globals . listener_mutex ) ;
2006-07-22 21:49:52 +00:00
}
2007-06-20 07:53:33 +00:00
SWITCH_STANDARD_APP ( socket_function )
2007-01-06 17:06:18 +00:00
{
2008-02-26 21:53:48 +00:00
char * host , * port_name , * path ;
2015-09-02 17:06:29 +00:00
switch_socket_t * new_sock = NULL ;
2007-03-29 22:31:56 +00:00
switch_sockaddr_t * sa ;
switch_port_t port = 8084 ;
listener_t * listener ;
2015-08-31 21:08:52 +00:00
unsigned int argc = 0 , x = 0 ;
2007-03-29 22:31:56 +00:00
char * argv [ 80 ] = { 0 } ;
2015-01-04 11:56:30 +00:00
char * hosts [ 50 ] = { 0 } ;
unsigned int hosts_count = 0 ;
switch_status_t connected = SWITCH_STATUS_FALSE ;
2007-01-06 17:06:18 +00:00
char * mydata ;
2008-02-26 21:53:48 +00:00
switch_channel_t * channel = NULL ;
2015-01-04 11:56:30 +00:00
char errbuf [ 512 ] = { 0 } ;
2008-02-26 21:53:48 +00:00
channel = switch_core_session_get_channel ( session ) ;
2007-01-06 17:06:18 +00:00
if ( data & & ( mydata = switch_core_session_strdup ( session , data ) ) ) {
argc = switch_separate_string ( mydata , ' ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
2007-03-29 22:31:56 +00:00
}
2007-01-06 17:06:18 +00:00
2007-03-29 22:31:56 +00:00
if ( argc < 1 ) {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Parse Error! \n " ) ;
2007-03-29 22:31:56 +00:00
return ;
}
2007-01-06 17:06:18 +00:00
2015-01-04 11:56:30 +00:00
hosts_count = switch_split ( argv [ 0 ] , ' | ' , hosts ) ;
2007-01-06 17:06:18 +00:00
2015-01-04 11:56:30 +00:00
for ( x = 0 ; x < hosts_count ; x + + ) {
host = hosts [ x ] ;
2007-01-06 17:06:18 +00:00
2015-01-04 11:56:30 +00:00
if ( zstr ( host ) ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Missing Host! \n " ) ;
continue ;
}
2007-01-06 17:06:18 +00:00
2015-01-04 11:56:30 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_NOTICE , " Trying host: %s \n " , host ) ;
2008-02-26 21:53:48 +00:00
2015-01-04 11:56:30 +00:00
if ( ( port_name = strrchr ( host , ' : ' ) ) ) {
* port_name + + = ' \0 ' ;
port = ( switch_port_t ) atoi ( port_name ) ;
}
2008-02-29 15:39:56 +00:00
2015-01-04 11:56:30 +00:00
if ( ( path = strchr ( ( port_name ? port_name : host ) , ' / ' ) ) ) {
* path + + = ' \0 ' ;
switch_channel_set_variable ( channel , " socket_path " , path ) ;
}
2007-01-06 17:06:18 +00:00
2015-01-04 11:56:30 +00:00
switch_channel_set_variable ( channel , " socket_host " , host ) ;
if ( switch_sockaddr_info_get ( & sa , host , SWITCH_UNSPEC , port , 0 , switch_core_session_get_pool ( session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Socket Error! \n " ) ;
continue ;
}
if ( switch_socket_create ( & new_sock , switch_sockaddr_get_family ( sa ) , SOCK_STREAM , SWITCH_PROTO_TCP , switch_core_session_get_pool ( session ) )
! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Socket Error! \n " ) ;
continue ;
}
switch_socket_opt_set ( new_sock , SWITCH_SO_KEEPALIVE , 1 ) ;
switch_socket_opt_set ( new_sock , SWITCH_SO_TCP_NODELAY , 1 ) ;
switch_socket_opt_set ( new_sock , SWITCH_SO_TCP_KEEPIDLE , 30 ) ;
switch_socket_opt_set ( new_sock , SWITCH_SO_TCP_KEEPINTVL , 30 ) ;
2007-01-06 17:06:18 +00:00
2015-01-04 11:56:30 +00:00
if ( ( connected = switch_socket_connect ( new_sock , sa ) ) = = SWITCH_STATUS_SUCCESS ) {
break ;
}
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Socket Error: %s \n " , switch_strerror ( errno , errbuf , sizeof ( errbuf ) ) ) ;
} //end hosts loop
2007-01-06 17:06:18 +00:00
2015-01-04 11:56:30 +00:00
if ( connected ! = SWITCH_STATUS_SUCCESS ) {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Socket Error! \n " ) ;
2007-03-29 22:31:56 +00:00
return ;
}
if ( ! ( listener = switch_core_session_alloc ( session , sizeof ( * listener ) ) ) ) {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Memory Error \n " ) ;
2007-01-06 17:06:18 +00:00
return ;
}
2007-03-29 22:31:56 +00:00
switch_thread_rwlock_create ( & listener - > rwlock , switch_core_session_get_pool ( session ) ) ;
2010-07-24 06:03:21 +00:00
switch_queue_create ( & listener - > event_queue , MAX_QUEUE_LEN , switch_core_session_get_pool ( session ) ) ;
switch_queue_create ( & listener - > log_queue , MAX_QUEUE_LEN , switch_core_session_get_pool ( session ) ) ;
2007-03-29 22:31:56 +00:00
listener - > sock = new_sock ;
listener - > pool = switch_core_session_get_pool ( session ) ;
listener - > format = EVENT_FORMAT_PLAIN ;
listener - > session = session ;
2010-01-05 19:47:49 +00:00
switch_set_flag ( listener , LFLAG_ALLOW_LOG ) ;
2007-03-29 22:31:56 +00:00
2012-06-26 14:58:51 +00:00
switch_socket_create_pollset ( & listener - > pollfd , listener - > sock , SWITCH_POLLIN | SWITCH_POLLERR , listener - > pool ) ;
2007-03-29 22:31:56 +00:00
switch_mutex_init ( & listener - > flag_mutex , SWITCH_MUTEX_NESTED , listener - > pool ) ;
2008-10-30 00:39:55 +00:00
switch_mutex_init ( & listener - > filter_mutex , SWITCH_MUTEX_NESTED , listener - > pool ) ;
2014-03-08 19:37:09 +00:00
switch_core_hash_init ( & listener - > event_hash ) ;
2007-03-29 22:31:56 +00:00
switch_set_flag ( listener , LFLAG_AUTHED ) ;
2008-12-12 15:44:37 +00:00
switch_set_flag ( listener , LFLAG_OUTBOUND ) ;
2007-03-29 22:31:56 +00:00
for ( x = 1 ; x < argc ; x + + ) {
if ( argv [ x ] & & ! strcasecmp ( argv [ x ] , " full " ) ) {
switch_set_flag ( listener , LFLAG_FULL ) ;
} else if ( argv [ x ] & & ! strcasecmp ( argv [ x ] , " async " ) ) {
switch_set_flag ( listener , LFLAG_ASYNC ) ;
}
}
2010-02-06 03:38:24 +00:00
if ( switch_test_flag ( listener , LFLAG_ASYNC ) ) {
2009-04-30 22:45:46 +00:00
const char * var ;
2010-02-06 03:38:24 +00:00
2007-03-29 22:31:56 +00:00
launch_listener_thread ( listener ) ;
2009-04-30 22:45:46 +00:00
2010-02-06 03:38:24 +00:00
while ( switch_channel_ready ( channel ) & & ! switch_test_flag ( listener , LFLAG_CONNECTED ) ) {
2009-04-30 22:45:46 +00:00
switch_cond_next ( ) ;
}
2010-02-06 03:38:24 +00:00
2007-03-29 22:31:56 +00:00
switch_ivr_park ( session , NULL ) ;
2009-04-30 22:45:46 +00:00
2009-10-13 21:52:47 +00:00
switch_ivr_parse_all_events ( session ) ;
2010-02-06 03:38:24 +00:00
2017-01-06 07:10:15 +00:00
if ( switch_channel_get_state ( channel ) ! = CS_HIBERNATE & &
! switch_channel_test_flag ( channel , CF_REDIRECT ) & & ! switch_channel_test_flag ( channel , CF_TRANSFER ) & & ! switch_channel_test_flag ( channel , CF_RESET )
2016-05-18 17:47:30 +00:00
& & ( switch_test_flag ( listener , LFLAG_RESUME ) | | ( ( var = switch_channel_get_variable ( channel , " socket_resume " ) ) & & switch_true ( var ) ) ) ) {
2009-04-30 22:45:46 +00:00
switch_channel_set_state ( channel , CS_EXECUTE ) ;
}
2008-11-11 13:32:11 +00:00
return ;
2007-03-29 22:31:56 +00:00
} else {
listener_run ( NULL , ( void * ) listener ) ;
}
2009-02-25 03:41:18 +00:00
if ( switch_channel_down ( channel ) ) {
2008-11-11 13:32:11 +00:00
while ( switch_test_flag ( listener , LFLAG_SESSION ) ) {
switch_yield ( 100000 ) ;
}
2007-03-29 22:31:56 +00:00
}
2007-01-06 17:06:18 +00:00
}
2010-02-06 03:38:24 +00:00
static void close_socket ( switch_socket_t * * sock )
2007-03-29 22:31:56 +00:00
{
2006-08-29 20:27:43 +00:00
switch_mutex_lock ( listen_list . sock_mutex ) ;
2006-07-22 21:49:52 +00:00
if ( * sock ) {
2007-03-09 20:44:13 +00:00
switch_socket_shutdown ( * sock , SWITCH_SHUTDOWN_READWRITE ) ;
2006-07-22 21:49:52 +00:00
switch_socket_close ( * sock ) ;
* sock = NULL ;
}
2006-08-29 20:27:43 +00:00
switch_mutex_unlock ( listen_list . sock_mutex ) ;
2006-07-22 21:49:52 +00:00
}
2007-06-13 17:06:10 +00:00
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_event_socket_shutdown )
2006-07-22 21:49:52 +00:00
{
2007-07-24 21:26:04 +00:00
int sanity = 0 ;
2006-07-25 14:14:07 +00:00
2006-11-09 05:39:04 +00:00
prefs . done = 1 ;
2009-02-20 01:10:59 +00:00
kill_all_listeners ( ) ;
2008-07-11 14:35:08 +00:00
switch_log_unbind_logger ( socket_logger ) ;
2006-08-29 20:27:43 +00:00
close_socket ( & listen_list . sock ) ;
2008-05-27 04:54:52 +00:00
while ( prefs . threads ) {
2009-02-20 01:10:59 +00:00
switch_yield ( 100000 ) ;
kill_all_listeners ( ) ;
if ( + + sanity > = 200 ) {
2007-07-24 21:26:04 +00:00
break ;
}
}
2006-08-29 20:27:43 +00:00
2009-02-20 01:10:59 +00:00
switch_event_unbind ( & globals . node ) ;
2006-07-22 21:49:52 +00:00
2009-02-23 19:17:24 +00:00
switch_safe_free ( prefs . ip ) ;
2010-02-06 03:38:24 +00:00
switch_safe_free ( prefs . password ) ;
2009-02-23 19:17:24 +00:00
2006-07-22 21:49:52 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-27 04:54:52 +00:00
static void add_listener ( listener_t * listener )
2006-07-22 21:49:52 +00:00
{
/* add me to the listeners so I get events */
2008-11-07 14:48:49 +00:00
switch_mutex_lock ( globals . listener_mutex ) ;
2006-07-22 21:49:52 +00:00
listener - > next = listen_list . listeners ;
listen_list . listeners = listener ;
2008-11-07 14:48:49 +00:00
switch_mutex_unlock ( globals . listener_mutex ) ;
2006-07-22 21:49:52 +00:00
}
2008-05-27 04:54:52 +00:00
static void remove_listener ( listener_t * listener )
2006-07-22 21:49:52 +00:00
{
listener_t * l , * last = NULL ;
2008-11-07 14:48:49 +00:00
switch_mutex_lock ( globals . listener_mutex ) ;
2006-07-22 21:49:52 +00:00
for ( l = listen_list . listeners ; l ; l = l - > next ) {
if ( l = = listener ) {
if ( last ) {
last - > next = l - > next ;
} else {
listen_list . listeners = l - > next ;
}
}
last = l ;
}
2008-11-07 14:48:49 +00:00
switch_mutex_unlock ( globals . listener_mutex ) ;
2006-07-22 21:49:52 +00:00
}
2011-01-25 20:13:15 +00:00
static void send_disconnect ( listener_t * listener , const char * message )
2010-07-24 06:03:21 +00:00
{
2017-01-06 07:10:15 +00:00
2011-01-25 20:13:15 +00:00
char disco_buf [ 512 ] = " " ;
switch_size_t len , mlen ;
if ( zstr ( message ) ) {
message = " Disconnected. \n " ;
}
mlen = strlen ( message ) ;
2017-01-06 07:10:15 +00:00
2011-01-25 20:13:15 +00:00
if ( listener - > session ) {
switch_snprintf ( disco_buf , sizeof ( disco_buf ) , " Content-Type: text/disconnect-notice \n "
" Controlled-Session-UUID: %s \n "
2014-01-22 21:28:53 +00:00
" Content-Disposition: disconnect \n " " Content-Length: %d \n \n " , switch_core_session_get_uuid ( listener - > session ) , ( int ) mlen ) ;
2011-01-25 20:13:15 +00:00
} else {
2014-01-22 21:28:53 +00:00
switch_snprintf ( disco_buf , sizeof ( disco_buf ) , " Content-Type: text/disconnect-notice \n Content-Length: %d \n \n " , ( int ) mlen ) ;
2011-01-25 20:13:15 +00:00
}
2013-03-21 04:58:15 +00:00
if ( ! listener - > sock ) return ;
2011-01-25 20:13:15 +00:00
len = strlen ( disco_buf ) ;
switch_socket_send ( listener - > sock , disco_buf , & len ) ;
if ( len > 0 ) {
len = mlen ;
switch_socket_send ( listener - > sock , message , & len ) ;
}
}
static void kill_listener ( listener_t * l , const char * message )
{
if ( message ) {
send_disconnect ( l , message ) ;
}
2010-07-24 06:03:21 +00:00
switch_clear_flag ( l , LFLAG_RUNNING ) ;
if ( l - > sock ) {
switch_socket_shutdown ( l - > sock , SWITCH_SHUTDOWN_READWRITE ) ;
switch_socket_close ( l - > sock ) ;
}
}
2008-10-23 17:31:22 +00:00
2009-02-20 01:10:59 +00:00
static void kill_all_listeners ( void )
{
listener_t * l ;
switch_mutex_lock ( globals . listener_mutex ) ;
for ( l = listen_list . listeners ; l ; l = l - > next ) {
2011-01-25 20:13:15 +00:00
kill_listener ( l , " The system is being shut down. \n " ) ;
2009-02-20 01:10:59 +00:00
}
switch_mutex_unlock ( globals . listener_mutex ) ;
}
2008-10-23 17:31:22 +00:00
static listener_t * find_listener ( uint32_t id )
{
listener_t * l , * r = NULL ;
2008-11-07 14:48:49 +00:00
switch_mutex_lock ( globals . listener_mutex ) ;
2008-10-23 17:31:22 +00:00
for ( l = listen_list . listeners ; l ; l = l - > next ) {
2009-11-06 20:17:31 +00:00
if ( l - > id & & l - > id = = id & & ! l - > expire_time ) {
2008-10-23 17:31:22 +00:00
if ( switch_thread_rwlock_tryrdlock ( l - > rwlock ) = = SWITCH_STATUS_SUCCESS ) {
r = l ;
}
break ;
}
}
2008-11-07 14:48:49 +00:00
switch_mutex_unlock ( globals . listener_mutex ) ;
2008-10-23 17:31:22 +00:00
return r ;
}
2006-07-22 21:49:52 +00:00
static void strip_cr ( char * s )
{
char * p ;
if ( ( p = strchr ( s , ' \r ' ) ) | | ( p = strchr ( s , ' \n ' ) ) ) {
* p = ' \0 ' ;
}
}
2008-10-23 17:31:22 +00:00
static void xmlize_listener ( listener_t * listener , switch_stream_handle_t * stream )
{
stream - > write_function ( stream , " <listener> \n " ) ;
stream - > write_function ( stream , " <listen-id>%u</listen-id> \n " , listener - > id ) ;
2010-06-17 16:43:09 +00:00
stream - > write_function ( stream , " <format>%s</format> \n " , format2str ( listener - > format ) ) ;
2008-10-23 17:31:22 +00:00
stream - > write_function ( stream , " <timeout>%u</timeout> \n " , listener - > timeout ) ;
stream - > write_function ( stream , " </listener> \n " ) ;
}
2008-11-14 17:29:14 +00:00
SWITCH_STANDARD_API ( event_sink_function )
2008-10-23 17:31:22 +00:00
{
char * http = NULL ;
char * wcmd = NULL ;
char * format = NULL ;
listener_t * listener = NULL ;
if ( stream - > param_event ) {
2010-02-06 03:38:24 +00:00
http = switch_event_get_header ( stream - > param_event , " http-host " ) ;
2008-10-23 17:31:22 +00:00
wcmd = switch_event_get_header ( stream - > param_event , " command " ) ;
format = switch_event_get_header ( stream - > param_event , " format " ) ;
2010-02-06 03:38:24 +00:00
}
2008-10-23 17:31:22 +00:00
if ( ! http ) {
2009-11-01 20:40:31 +00:00
stream - > write_function ( stream , " This is a web application! \n " ) ;
2010-02-06 03:38:24 +00:00
return SWITCH_STATUS_SUCCESS ;
2008-10-23 17:31:22 +00:00
}
2010-02-06 03:38:24 +00:00
2014-02-28 22:11:22 +00:00
if ( ! format ) {
format = " xml " ;
}
if ( switch_stristr ( " json " , format ) ) {
stream - > write_function ( stream , " Content-Type: application/json \n \n " ) ;
} else {
stream - > write_function ( stream , " Content-Type: text/xml \n \n " ) ;
stream - > write_function ( stream , " <?xml version= \" 1.0 \" ?> \n " ) ;
stream - > write_function ( stream , " <root> \n " ) ;
}
2010-02-06 03:38:24 +00:00
2008-10-23 17:31:22 +00:00
if ( ! wcmd ) {
stream - > write_function ( stream , " <data><reply type= \" error \" >Missing command parameter!</reply></data> \n " ) ;
goto end ;
}
2010-02-06 03:38:24 +00:00
2008-11-14 17:29:14 +00:00
if ( ! strcasecmp ( wcmd , " filter " ) ) {
2008-11-14 18:11:54 +00:00
char * action = switch_event_get_header ( stream - > param_event , " action " ) ;
char * header_name = switch_event_get_header ( stream - > param_event , " header-name " ) ;
char * header_val = switch_event_get_header ( stream - > param_event , " header-val " ) ;
char * id = switch_event_get_header ( stream - > param_event , " listen-id " ) ;
uint32_t idl = 0 ;
if ( id ) {
idl = ( uint32_t ) atol ( id ) ;
}
if ( ! ( listener = find_listener ( idl ) ) ) {
stream - > write_function ( stream , " <data><reply type= \" error \" >Invalid Listen-ID</reply></data> \n " ) ;
2010-02-06 03:38:24 +00:00
goto end ;
2008-11-14 18:11:54 +00:00
}
2009-10-23 16:03:42 +00:00
if ( zstr ( action ) ) {
2008-11-14 17:29:14 +00:00
stream - > write_function ( stream , " <data><reply type= \" error \" >Invalid Syntax</reply></data> \n " ) ;
2010-02-06 03:38:24 +00:00
goto end ;
2008-11-14 17:29:14 +00:00
}
2010-02-06 03:38:24 +00:00
switch_mutex_lock ( listener - > filter_mutex ) ;
2008-11-14 17:29:14 +00:00
if ( ! listener - > filters ) {
2010-11-22 23:06:59 +00:00
switch_event_create_plain ( & listener - > filters , SWITCH_EVENT_CLONE ) ;
2008-11-14 17:29:14 +00:00
}
if ( ! strcasecmp ( action , " delete " ) ) {
2009-10-23 16:03:42 +00:00
if ( zstr ( header_val ) ) {
2008-11-14 17:29:14 +00:00
stream - > write_function ( stream , " <data><reply type= \" error \" >Invalid Syntax</reply></data> \n " ) ;
goto filter_end ;
}
if ( ! strcasecmp ( header_val , " all " ) ) {
switch_event_destroy ( & listener - > filters ) ;
2010-11-22 23:06:59 +00:00
switch_event_create_plain ( & listener - > filters , SWITCH_EVENT_CLONE ) ;
2008-11-14 17:29:14 +00:00
} else {
switch_event_del_header ( listener - > filters , header_val ) ;
}
stream - > write_function ( stream , " <data> \n <reply type= \" success \" >filter deleted.</reply> \n <api-command> \n " ) ;
} else if ( ! strcasecmp ( action , " add " ) ) {
2009-10-23 16:03:42 +00:00
if ( zstr ( header_name ) | | zstr ( header_val ) ) {
2008-11-14 17:29:14 +00:00
stream - > write_function ( stream , " <data><reply type= \" error \" >Invalid Syntax</reply></data> \n " ) ;
goto filter_end ;
}
switch_event_add_header_string ( listener - > filters , SWITCH_STACK_BOTTOM , header_name , header_val ) ;
stream - > write_function ( stream , " <data> \n <reply type= \" success \" >filter added.</reply> \n <api-command> \n " ) ;
} else {
stream - > write_function ( stream , " <data><reply type= \" error \" >Invalid Syntax</reply></data> \n " ) ;
}
2010-02-06 03:38:24 +00:00
filter_end :
2008-11-14 17:29:14 +00:00
switch_mutex_unlock ( listener - > filter_mutex ) ;
2008-12-31 22:44:23 +00:00
} else if ( ! strcasecmp ( wcmd , " stop-logging " ) ) {
char * id = switch_event_get_header ( stream - > param_event , " listen-id " ) ;
uint32_t idl = 0 ;
if ( id ) {
idl = ( uint32_t ) atol ( id ) ;
}
if ( ! ( listener = find_listener ( idl ) ) ) {
stream - > write_function ( stream , " <data><reply type= \" error \" >Invalid Listen-ID</reply></data> \n " ) ;
2010-02-06 03:38:24 +00:00
goto end ;
2008-12-31 22:44:23 +00:00
}
if ( switch_test_flag ( listener , LFLAG_LOG ) ) {
switch_clear_flag_locked ( listener , LFLAG_LOG ) ;
stream - > write_function ( stream , " <data><reply type= \" success \" >Not Logging</reply></data> \n " ) ;
} else {
stream - > write_function ( stream , " <data><reply type= \" error \" >Not Logging</reply></data> \n " ) ;
}
goto end ;
} else if ( ! strcasecmp ( wcmd , " set-loglevel " ) ) {
char * loglevel = switch_event_get_header ( stream - > param_event , " loglevel " ) ;
char * id = switch_event_get_header ( stream - > param_event , " listen-id " ) ;
uint32_t idl = 0 ;
if ( id ) {
idl = ( uint32_t ) atol ( id ) ;
}
if ( ! ( listener = find_listener ( idl ) ) ) {
stream - > write_function ( stream , " <data><reply type= \" error \" >Invalid Listen-ID</reply></data> \n " ) ;
2010-02-06 03:38:24 +00:00
goto end ;
2008-12-31 22:44:23 +00:00
}
if ( loglevel ) {
switch_log_level_t ltype = switch_log_str2level ( loglevel ) ;
if ( ltype ! = SWITCH_LOG_INVALID ) {
listener - > level = ltype ;
switch_set_flag ( listener , LFLAG_LOG ) ;
stream - > write_function ( stream , " <data><reply type= \" success \" >Log Level %s</reply></data> \n " , loglevel ) ;
} else {
stream - > write_function ( stream , " <data><reply type= \" error \" >Invalid Level</reply></data> \n " ) ;
}
} else {
stream - > write_function ( stream , " <data><reply type= \" error \" >Invalid Syntax</reply></data> \n " ) ;
}
goto end ;
2008-11-14 17:29:14 +00:00
} else if ( ! strcasecmp ( wcmd , " create-listener " ) ) {
2008-10-23 17:31:22 +00:00
char * events = switch_event_get_header ( stream - > param_event , " events " ) ;
2008-12-31 22:44:23 +00:00
char * loglevel = switch_event_get_header ( stream - > param_event , " loglevel " ) ;
2008-10-23 17:31:22 +00:00
switch_memory_pool_t * pool ;
char * next , * cur ;
uint32_t count = 0 , key_count = 0 ;
uint8_t custom = 0 ;
char * edup ;
2010-02-06 03:38:24 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( events ) & & zstr ( loglevel ) ) {
2014-02-28 22:11:22 +00:00
if ( switch_stristr ( " json " , format ) ) {
stream - > write_function ( stream , " { \" reply \" : \" error \" , \" reply_text \" : \" Missing parameter! \" } " ) ;
} else {
stream - > write_function ( stream , " <data><reply type= \" error \" >Missing parameter!</reply></data> \n " ) ;
}
2008-10-23 17:31:22 +00:00
goto end ;
}
switch_core_new_memory_pool ( & pool ) ;
listener = switch_core_alloc ( pool , sizeof ( * listener ) ) ;
listener - > pool = pool ;
listener - > format = EVENT_FORMAT_PLAIN ;
switch_mutex_init ( & listener - > flag_mutex , SWITCH_MUTEX_NESTED , listener - > pool ) ;
2008-10-30 00:39:55 +00:00
switch_mutex_init ( & listener - > filter_mutex , SWITCH_MUTEX_NESTED , listener - > pool ) ;
2012-06-26 14:58:51 +00:00
2014-03-08 19:37:09 +00:00
switch_core_hash_init ( & listener - > event_hash ) ;
2008-10-23 17:31:22 +00:00
switch_set_flag ( listener , LFLAG_AUTHED ) ;
switch_set_flag ( listener , LFLAG_STATEFUL ) ;
2010-01-05 19:47:49 +00:00
switch_set_flag ( listener , LFLAG_ALLOW_LOG ) ;
2010-07-24 06:03:21 +00:00
switch_queue_create ( & listener - > event_queue , MAX_QUEUE_LEN , listener - > pool ) ;
switch_queue_create ( & listener - > log_queue , MAX_QUEUE_LEN , listener - > pool ) ;
2008-12-31 22:44:23 +00:00
if ( loglevel ) {
switch_log_level_t ltype = switch_log_str2level ( loglevel ) ;
if ( ltype ! = SWITCH_LOG_INVALID ) {
listener - > level = ltype ;
switch_set_flag ( listener , LFLAG_LOG ) ;
}
}
2008-10-23 17:31:22 +00:00
switch_thread_rwlock_create ( & listener - > rwlock , listener - > pool ) ;
listener - > id = next_id ( ) ;
listener - > timeout = 60 ;
2009-01-25 21:23:07 +00:00
listener - > last_flush = switch_epoch_time_now ( NULL ) ;
2010-02-06 03:38:24 +00:00
2008-12-31 22:44:23 +00:00
if ( events ) {
2009-01-02 17:39:31 +00:00
char delim = ' , ' ;
2008-10-23 17:31:22 +00:00
2008-12-31 22:44:23 +00:00
if ( switch_stristr ( " xml " , format ) ) {
listener - > format = EVENT_FORMAT_XML ;
2010-06-17 16:43:09 +00:00
} else if ( switch_stristr ( " json " , format ) ) {
listener - > format = EVENT_FORMAT_JSON ;
2008-12-31 22:44:23 +00:00
} else {
listener - > format = EVENT_FORMAT_PLAIN ;
2008-10-23 17:31:22 +00:00
}
2010-02-06 03:38:24 +00:00
2008-12-31 22:44:23 +00:00
edup = strdup ( events ) ;
2009-01-02 17:39:31 +00:00
2019-07-12 15:58:32 +00:00
switch_assert ( edup ) ;
2009-01-02 17:39:31 +00:00
if ( strchr ( edup , ' ' ) ) {
delim = ' ' ;
}
2008-12-31 22:44:23 +00:00
for ( cur = edup ; cur ; count + + ) {
switch_event_types_t type ;
2010-02-06 03:38:24 +00:00
2009-01-02 17:39:31 +00:00
if ( ( next = strchr ( cur , delim ) ) ) {
2008-12-31 22:44:23 +00:00
* next + + = ' \0 ' ;
}
2008-10-23 17:31:22 +00:00
2008-12-31 22:44:23 +00:00
if ( custom ) {
switch_core_hash_insert ( listener - > event_hash , cur , MARKER ) ;
} else if ( switch_name_event ( cur , & type ) = = SWITCH_STATUS_SUCCESS ) {
key_count + + ;
if ( type = = SWITCH_EVENT_ALL ) {
uint32_t x = 0 ;
for ( x = 0 ; x < SWITCH_EVENT_ALL ; x + + ) {
listener - > event_list [ x ] = 1 ;
}
}
if ( type < = SWITCH_EVENT_ALL ) {
listener - > event_list [ type ] = 1 ;
}
if ( type = = SWITCH_EVENT_CUSTOM ) {
custom + + ;
2008-10-23 17:31:22 +00:00
}
}
2010-02-06 03:38:24 +00:00
2008-12-31 22:44:23 +00:00
cur = next ;
2008-10-23 17:31:22 +00:00
}
2010-02-06 03:38:24 +00:00
2008-10-23 17:31:22 +00:00
2008-12-31 22:44:23 +00:00
switch_safe_free ( edup ) ;
2008-10-23 17:31:22 +00:00
2008-12-31 22:44:23 +00:00
if ( ! key_count ) {
switch_core_hash_destroy ( & listener - > event_hash ) ;
switch_core_destroy_memory_pool ( & listener - > pool ) ;
2014-02-28 22:11:22 +00:00
if ( listener - > format = = EVENT_FORMAT_JSON ) {
stream - > write_function ( stream , " { \" reply \" : \" error \" , \" reply_text \" : \" No keywords supplied \" } " ) ;
} else {
stream - > write_function ( stream , " <data><reply type= \" error \" >No keywords supplied</reply></data> \n " ) ;
}
2008-12-31 22:44:23 +00:00
goto end ;
}
2008-10-23 17:31:22 +00:00
}
switch_set_flag_locked ( listener , LFLAG_EVENTS ) ;
add_listener ( listener ) ;
2014-02-28 22:11:22 +00:00
if ( listener - > format = = EVENT_FORMAT_JSON ) {
cJSON * cj , * cjlistener ;
char * p ;
cj = cJSON_CreateObject ( ) ;
cjlistener = cJSON_CreateObject ( ) ;
cJSON_AddNumberToObject ( cjlistener , " listen-id " , listener - > id ) ;
cJSON_AddItemToObject ( cjlistener , " format " , cJSON_CreateString ( format2str ( listener - > format ) ) ) ;
cJSON_AddNumberToObject ( cjlistener , " timeout " , listener - > timeout ) ;
cJSON_AddItemToObject ( cj , " listener " , cjlistener ) ;
p = cJSON_Print ( cj ) ;
stream - > write_function ( stream , p ) ;
switch_safe_free ( p ) ;
cJSON_Delete ( cj ) ;
} else {
stream - > write_function ( stream , " <data> \n " ) ;
stream - > write_function ( stream , " <reply type= \" success \" >Listener %u Created</reply> \n " , listener - > id ) ;
xmlize_listener ( listener , stream ) ;
stream - > write_function ( stream , " </data> \n " ) ;
}
2008-10-23 17:31:22 +00:00
2009-05-02 00:58:51 +00:00
if ( globals . debug > 0 ) {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Creating event-sink listener [%u] \n " , listener - > id ) ;
2009-05-02 00:58:51 +00:00
}
2010-02-06 03:38:24 +00:00
2008-10-23 17:31:22 +00:00
goto end ;
2010-02-06 03:38:24 +00:00
} else if ( ! strcasecmp ( wcmd , " destroy-listener " ) ) {
2008-10-23 17:31:22 +00:00
char * id = switch_event_get_header ( stream - > param_event , " listen-id " ) ;
2008-10-24 15:50:46 +00:00
uint32_t idl = 0 ;
if ( id ) {
idl = ( uint32_t ) atol ( id ) ;
}
2008-10-23 17:31:22 +00:00
if ( ( listener = find_listener ( idl ) ) ) {
2009-05-02 00:58:51 +00:00
if ( globals . debug > 0 ) {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Destroying event-sink listener [%u] \n " , idl ) ;
2009-05-02 00:58:51 +00:00
}
2008-10-23 17:31:22 +00:00
stream - > write_function ( stream , " <data> \n <reply type= \" success \" >listener %u destroyed</reply> \n " , listener - > id ) ;
xmlize_listener ( listener , stream ) ;
stream - > write_function ( stream , " </data> \n " ) ;
2009-11-06 20:17:31 +00:00
listener - > expire_time = switch_epoch_time_now ( NULL ) ;
2008-10-23 17:31:22 +00:00
goto end ;
} else {
2009-05-02 00:58:51 +00:00
if ( globals . debug > 0 ) {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Request to destroy unknown event-sink listener [%u] \n " , idl ) ;
2009-05-02 00:58:51 +00:00
}
2008-10-23 17:31:22 +00:00
stream - > write_function ( stream , " <data><reply type= \" error \" >Can't find listener</reply></data> \n " ) ;
goto end ;
}
} else if ( ! strcasecmp ( wcmd , " check-listener " ) ) {
char * id = switch_event_get_header ( stream - > param_event , " listen-id " ) ;
2008-10-24 15:50:46 +00:00
uint32_t idl = 0 ;
2008-10-23 17:31:22 +00:00
void * pop ;
2008-10-24 15:50:46 +00:00
switch_event_t * pevent = NULL ;
2014-02-28 22:11:22 +00:00
cJSON * cj = NULL , * cjevents = NULL ;
2010-02-06 03:38:24 +00:00
2008-10-24 15:50:46 +00:00
if ( id ) {
idl = ( uint32_t ) atol ( id ) ;
}
2008-10-23 17:31:22 +00:00
if ( ! ( listener = find_listener ( idl ) ) ) {
2014-02-28 22:11:22 +00:00
if ( switch_stristr ( " json " , format ) ) {
stream - > write_function ( stream , " { \" reply \" : \" error \" , \" reply_text \" : \" Can't find listener \" } " ) ;
} else {
stream - > write_function ( stream , " <data><reply type= \" error \" >Can't find listener</reply></data> \n " ) ;
}
2008-10-23 17:31:22 +00:00
goto end ;
}
2009-01-25 21:23:07 +00:00
listener - > last_flush = switch_epoch_time_now ( NULL ) ;
2014-02-28 22:11:22 +00:00
if ( listener - > format = = EVENT_FORMAT_JSON ) {
cJSON * cjlistener ;
cj = cJSON_CreateObject ( ) ;
cjlistener = cJSON_CreateObject ( ) ;
cJSON_AddNumberToObject ( cjlistener , " listen-id " , listener - > id ) ;
cJSON_AddItemToObject ( cjlistener , " format " , cJSON_CreateString ( format2str ( listener - > format ) ) ) ;
cJSON_AddNumberToObject ( cjlistener , " timeout " , listener - > timeout ) ;
cJSON_AddItemToObject ( cj , " listener " , cjlistener ) ;
} else {
stream - > write_function ( stream , " <data> \n <reply type= \" success \" >Current Events Follow</reply> \n " ) ;
xmlize_listener ( listener , stream ) ;
}
2008-12-31 22:44:23 +00:00
if ( switch_test_flag ( listener , LFLAG_LOG ) ) {
stream - > write_function ( stream , " <log_data> \n " ) ;
while ( switch_queue_trypop ( listener - > log_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
switch_log_node_t * dnode = ( switch_log_node_t * ) pop ;
2014-01-22 21:28:53 +00:00
size_t encode_len = ( strlen ( dnode - > data ) * 3 ) + 1 ;
2008-12-31 22:44:23 +00:00
char * encode_buf = malloc ( encode_len ) ;
2010-02-06 03:38:24 +00:00
2008-12-31 22:44:23 +00:00
switch_assert ( encode_buf ) ;
2010-02-06 03:38:24 +00:00
2008-12-31 22:44:23 +00:00
memset ( encode_buf , 0 , encode_len ) ;
switch_url_encode ( ( char * ) dnode - > data , encode_buf , encode_len ) ;
2010-02-06 03:38:24 +00:00
stream - > write_function ( stream ,
" <log log-level= \" %d \" text-channel= \" %d \" log-file= \" %s \" log-func= \" %s \" log-line= \" %d \" user-data= \" %s \" >%s</log> \n " ,
dnode - > level , dnode - > channel , dnode - > file , dnode - > func , dnode - > line , switch_str_nil ( dnode - > userdata ) , encode_buf ) ;
2008-12-31 22:44:23 +00:00
free ( encode_buf ) ;
2009-08-22 19:26:58 +00:00
switch_log_node_free ( & dnode ) ;
2008-12-31 22:44:23 +00:00
}
stream - > write_function ( stream , " </log_data> \n " ) ;
}
2014-02-28 22:11:22 +00:00
if ( listener - > format = = EVENT_FORMAT_JSON ) {
cjevents = cJSON_CreateArray ( ) ;
} else {
stream - > write_function ( stream , " <events> \n " ) ;
}
2008-10-23 17:31:22 +00:00
while ( switch_queue_trypop ( listener - > event_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
2011-04-22 21:43:29 +00:00
//char *etype;
2008-10-24 15:50:46 +00:00
pevent = ( switch_event_t * ) pop ;
2008-10-23 17:31:22 +00:00
if ( listener - > format = = EVENT_FORMAT_PLAIN ) {
2011-04-22 21:43:29 +00:00
//etype = "plain";
2008-10-23 17:31:22 +00:00
switch_event_serialize ( pevent , & listener - > ebuf , SWITCH_TRUE ) ;
stream - > write_function ( stream , " <event type= \" plain \" > \n %s</event> " , listener - > ebuf ) ;
2010-06-17 16:43:09 +00:00
} else if ( listener - > format = = EVENT_FORMAT_JSON ) {
2011-04-22 21:43:29 +00:00
//etype = "json";
2014-02-28 22:11:22 +00:00
cJSON * cjevent = NULL ;
switch_event_serialize_json_obj ( pevent , & cjevent ) ;
cJSON_AddItemToArray ( cjevents , cjevent ) ;
2008-10-23 17:31:22 +00:00
} else {
switch_xml_t xml ;
2011-04-22 21:43:29 +00:00
//etype = "xml";
2008-10-23 17:31:22 +00:00
2010-08-14 22:39:49 +00:00
if ( ( xml = switch_event_xmlize ( pevent , SWITCH_VA_NONE ) ) ) {
2008-10-23 17:31:22 +00:00
listener - > ebuf = switch_xml_toxml ( xml , SWITCH_FALSE ) ;
switch_xml_free ( xml ) ;
} else {
2008-10-23 21:58:09 +00:00
stream - > write_function ( stream , " <data><reply type= \" error \" >XML Render Error</reply></data> \n " ) ;
2008-10-23 17:31:22 +00:00
break ;
}
stream - > write_function ( stream , " %s \n " , listener - > ebuf ) ;
}
2010-02-06 03:38:24 +00:00
2008-10-23 17:31:22 +00:00
switch_safe_free ( listener - > ebuf ) ;
switch_event_destroy ( & pevent ) ;
}
2014-02-28 22:11:22 +00:00
if ( listener - > format = = EVENT_FORMAT_JSON ) {
char * p = " {} " ;
cJSON_AddItemToObject ( cj , " events " , cjevents ) ;
p = cJSON_Print ( cj ) ;
if ( cj & & p ) stream - > write_function ( stream , p ) ;
switch_safe_free ( p ) ;
cJSON_Delete ( cj ) ;
cj = NULL ;
} else {
stream - > write_function ( stream , " </events> \n </data> \n " ) ;
}
2008-10-23 17:31:22 +00:00
if ( pevent ) {
switch_event_destroy ( & pevent ) ;
}
switch_thread_rwlock_unlock ( listener - > rwlock ) ;
} else if ( ! strcasecmp ( wcmd , " exec-fsapi " ) ) {
char * api_command = switch_event_get_header ( stream - > param_event , " fsapi-command " ) ;
char * api_args = switch_event_get_header ( stream - > param_event , " fsapi-args " ) ;
switch_event_t * event , * oevent ;
2010-02-06 03:38:24 +00:00
2008-10-23 17:31:22 +00:00
if ( ! ( api_command ) ) {
stream - > write_function ( stream , " <data><reply type= \" error \" >INVALID API COMMAND!</reply></data> \n " ) ;
goto end ;
}
stream - > write_function ( stream , " <data> \n <reply type= \" success \" >Execute API Command</reply> \n <api-command> \n " ) ;
switch_event_create ( & event , SWITCH_EVENT_REQUEST_PARAMS ) ;
oevent = stream - > param_event ;
stream - > param_event = event ;
2009-02-27 16:35:42 +00:00
if ( ! strcasecmp ( api_command , " unload " ) & & ! strcasecmp ( api_args , " mod_event_socket " ) ) {
api_command = " bgapi " ;
api_args = " unload mod_event_socket " ;
2009-02-27 20:21:48 +00:00
} else if ( ! strcasecmp ( api_command , " reload " ) & & ! strcasecmp ( api_args , " mod_event_socket " ) ) {
api_command = " bgapi " ;
api_args = " reload mod_event_socket " ;
2009-02-27 16:35:42 +00:00
}
2008-10-23 17:31:22 +00:00
switch_api_execute ( api_command , api_args , NULL , stream ) ;
stream - > param_event = oevent ;
stream - > write_function ( stream , " </api-command> \n </data> " ) ;
} else {
stream - > write_function ( stream , " <data><reply type= \" error \" >INVALID COMMAND!</reply></data \n " ) ;
}
2010-02-06 03:38:24 +00:00
end :
2008-10-23 17:31:22 +00:00
2014-02-28 22:11:22 +00:00
if ( switch_stristr ( " json " , format ) ) {
} else {
stream - > write_function ( stream , " </root> \n \n " ) ;
}
2010-02-06 03:38:24 +00:00
2008-10-23 17:31:22 +00:00
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_MODULE_LOAD_FUNCTION ( mod_event_socket_load )
{
switch_application_interface_t * app_interface ;
switch_api_interface_t * api_interface ;
2009-02-23 19:17:24 +00:00
memset ( & globals , 0 , sizeof ( globals ) ) ;
2008-11-07 14:48:49 +00:00
switch_mutex_init ( & globals . listener_mutex , SWITCH_MUTEX_NESTED , pool ) ;
2008-12-31 19:07:20 +00:00
memset ( & listen_list , 0 , sizeof ( listen_list ) ) ;
switch_mutex_init ( & listen_list . sock_mutex , SWITCH_MUTEX_NESTED , pool ) ;
2008-11-07 23:25:38 +00:00
if ( switch_event_bind_removable ( modname , SWITCH_EVENT_ALL , SWITCH_EVENT_SUBCLASS_ANY , event_handler , NULL , & globals . node ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
return SWITCH_STATUS_GENERR ;
}
2010-02-06 03:38:24 +00:00
2008-11-07 23:25:38 +00:00
switch_log_bind_logger ( socket_logger , SWITCH_LOG_DEBUG , SWITCH_FALSE ) ;
2008-10-23 17:31:22 +00:00
/* connect my internal structure to the blank pointer passed to me */
* module_interface = switch_loadable_module_create_module_interface ( pool , modname ) ;
SWITCH_ADD_APP ( app_interface , " socket " , " Connect to a socket " , " Connect to a socket " , socket_function , " <ip>[:<port>] " , SAF_SUPPORT_NOMEDIA ) ;
2008-11-14 17:29:14 +00:00
SWITCH_ADD_API ( api_interface , " event_sink " , " event_sink " , event_sink_function , " <web data> " ) ;
2008-10-23 17:31:22 +00:00
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS ;
}
2008-05-27 04:54:52 +00:00
static switch_status_t read_packet ( listener_t * listener , switch_event_t * * event , uint32_t timeout )
2006-07-25 14:14:07 +00:00
{
2006-09-28 01:39:42 +00:00
switch_size_t mlen , bytes = 0 ;
2011-10-20 15:19:39 +00:00
char * mbuf = NULL ;
2006-07-25 14:14:07 +00:00
char buf [ 1024 ] = " " ;
switch_size_t len ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2006-09-28 01:39:42 +00:00
int count = 0 ;
2006-07-25 14:14:07 +00:00
uint32_t elapsed = 0 ;
time_t start = 0 ;
void * pop ;
char * ptr ;
uint8_t crcount = 0 ;
2011-10-20 15:19:39 +00:00
uint32_t max_len = 10485760 , block_len = 2048 , buf_len = 0 ;
2007-12-04 00:21:32 +00:00
switch_channel_t * channel = NULL ;
2008-07-22 22:23:50 +00:00
int clen = 0 ;
2009-02-20 01:10:59 +00:00
2006-07-25 14:14:07 +00:00
* event = NULL ;
2009-02-20 01:10:59 +00:00
if ( prefs . done ) {
2011-10-20 15:19:39 +00:00
switch_goto_status ( SWITCH_STATUS_FALSE , end ) ;
2009-02-20 01:10:59 +00:00
}
2011-10-20 15:19:39 +00:00
switch_zmalloc ( mbuf , block_len ) ;
switch_assert ( mbuf ) ;
buf_len = block_len ;
2009-01-25 21:23:07 +00:00
start = switch_epoch_time_now ( NULL ) ;
2006-07-25 14:14:07 +00:00
ptr = mbuf ;
2007-12-04 00:21:32 +00:00
if ( listener - > session ) {
channel = switch_core_session_get_channel ( listener - > session ) ;
}
2007-07-24 21:26:04 +00:00
while ( listener - > sock & & ! prefs . done ) {
2006-07-25 14:14:07 +00:00
uint8_t do_sleep = 1 ;
mlen = 1 ;
2011-10-20 15:19:39 +00:00
if ( bytes = = buf_len - 1 ) {
char * tmp ;
int pos ;
2014-01-22 21:28:53 +00:00
pos = ( int ) ( ptr - mbuf ) ;
2011-10-20 15:19:39 +00:00
buf_len + = block_len ;
tmp = realloc ( mbuf , buf_len ) ;
switch_assert ( tmp ) ;
mbuf = tmp ;
memset ( mbuf + bytes , 0 , buf_len - bytes ) ;
ptr = ( mbuf + pos ) ;
}
2017-01-06 07:10:15 +00:00
2009-02-21 23:19:58 +00:00
status = switch_socket_recv ( listener - > sock , ptr , & mlen ) ;
2010-02-06 03:38:24 +00:00
2009-02-20 01:10:59 +00:00
if ( prefs . done | | ( ! SWITCH_STATUS_IS_BREAK ( status ) & & status ! = SWITCH_STATUS_SUCCESS ) ) {
2011-10-20 15:19:39 +00:00
switch_goto_status ( SWITCH_STATUS_FALSE , end ) ;
2006-07-25 14:14:07 +00:00
}
2006-08-11 18:20:04 +00:00
if ( mlen ) {
2006-09-25 20:04:40 +00:00
bytes + = mlen ;
2006-08-11 18:20:04 +00:00
do_sleep = 0 ;
2006-07-25 14:14:07 +00:00
2007-03-29 22:31:56 +00:00
if ( * mbuf = = ' \r ' | | * mbuf = = ' \n ' ) { /* bah */
2006-07-25 14:14:07 +00:00
ptr = mbuf ;
2006-08-11 18:59:25 +00:00
mbuf [ 0 ] = ' \0 ' ;
2006-09-25 20:04:40 +00:00
bytes = 0 ;
2006-07-25 14:14:07 +00:00
continue ;
}
if ( * ptr = = ' \n ' ) {
crcount + + ;
} else if ( * ptr ! = ' \r ' ) {
crcount = 0 ;
}
ptr + + ;
2006-09-25 20:04:40 +00:00
if ( bytes > = max_len ) {
crcount = 2 ;
}
2006-07-25 14:14:07 +00:00
if ( crcount = = 2 ) {
char * next ;
char * cur = mbuf ;
2007-03-29 22:31:56 +00:00
while ( cur ) {
2006-07-25 14:14:07 +00:00
if ( ( next = strchr ( cur , ' \r ' ) ) | | ( next = strchr ( cur , ' \n ' ) ) ) {
while ( * next = = ' \r ' | | * next = = ' \n ' ) {
next + + ;
}
}
count + + ;
if ( count = = 1 ) {
2012-06-08 17:06:35 +00:00
switch_event_create ( event , SWITCH_EVENT_CLONE ) ;
2009-04-21 01:02:45 +00:00
switch_event_add_header_string ( * event , SWITCH_STACK_BOTTOM , " Command " , mbuf ) ;
2006-09-07 03:58:01 +00:00
} else if ( cur ) {
2006-07-25 14:14:07 +00:00
char * var , * val ;
2006-09-07 03:58:01 +00:00
var = cur ;
strip_cr ( var ) ;
2009-10-23 16:03:42 +00:00
if ( ! zstr ( var ) ) {
2006-09-07 03:58:01 +00:00
if ( ( val = strchr ( var , ' : ' ) ) ) {
* val + + = ' \0 ' ;
2007-03-29 22:31:56 +00:00
while ( * val = = ' ' ) {
2006-09-07 03:58:01 +00:00
val + + ;
}
2007-03-29 22:31:56 +00:00
}
2019-07-12 15:58:32 +00:00
if ( val ) {
2008-08-16 02:19:43 +00:00
switch_event_add_header_string ( * event , SWITCH_STACK_BOTTOM , var , val ) ;
2008-07-22 22:23:50 +00:00
if ( ! strcasecmp ( var , " content-length " ) ) {
clen = atoi ( val ) ;
2010-02-06 03:38:24 +00:00
2008-07-22 22:23:50 +00:00
if ( clen > 0 ) {
2008-07-23 13:45:35 +00:00
char * body ;
2008-07-24 08:11:34 +00:00
char * p ;
2010-02-06 03:38:24 +00:00
2008-07-23 13:45:35 +00:00
switch_zmalloc ( body , clen + 1 ) ;
2008-07-22 22:23:50 +00:00
2008-07-24 08:11:34 +00:00
p = body ;
2010-02-06 03:38:24 +00:00
while ( clen > 0 ) {
2008-07-22 22:23:50 +00:00
mlen = clen ;
2010-02-06 03:38:24 +00:00
2008-07-24 08:11:34 +00:00
status = switch_socket_recv ( listener - > sock , p , & mlen ) ;
2008-07-22 22:23:50 +00:00
2009-02-20 01:10:59 +00:00
if ( prefs . done | | ( ! SWITCH_STATUS_IS_BREAK ( status ) & & status ! = SWITCH_STATUS_SUCCESS ) ) {
2017-01-06 07:10:15 +00:00
free ( body ) ;
2011-10-20 15:19:39 +00:00
switch_goto_status ( SWITCH_STATUS_FALSE , end ) ;
2008-07-22 22:23:50 +00:00
}
2010-02-06 03:38:24 +00:00
2009-01-16 15:32:10 +00:00
/*
2010-02-06 03:38:24 +00:00
if ( channel & & ! switch_channel_ready ( channel ) ) {
status = SWITCH_STATUS_FALSE ;
break ;
}
*/
2008-07-22 22:23:50 +00:00
clen - = ( int ) mlen ;
2008-07-24 08:11:34 +00:00
p + = mlen ;
2008-07-22 22:23:50 +00:00
}
2010-02-06 03:38:24 +00:00
2008-07-22 22:23:50 +00:00
switch_event_add_body ( * event , " %s " , body ) ;
free ( body ) ;
}
}
2006-07-25 14:14:07 +00:00
}
}
}
2010-02-06 03:38:24 +00:00
2006-07-25 14:14:07 +00:00
cur = next ;
}
break ;
}
}
2010-02-06 03:38:24 +00:00
2006-07-25 14:14:07 +00:00
if ( timeout ) {
2009-01-25 21:23:07 +00:00
elapsed = ( uint32_t ) ( switch_epoch_time_now ( NULL ) - start ) ;
2006-07-25 14:14:07 +00:00
if ( elapsed > = timeout ) {
switch_clear_flag_locked ( listener , LFLAG_RUNNING ) ;
2011-10-20 15:19:39 +00:00
switch_goto_status ( SWITCH_STATUS_FALSE , end ) ;
2006-07-25 14:14:07 +00:00
}
}
2007-03-29 22:31:56 +00:00
2006-07-25 14:14:07 +00:00
if ( ! * mbuf ) {
if ( switch_test_flag ( listener , LFLAG_LOG ) ) {
if ( switch_queue_trypop ( listener - > log_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
2008-12-20 14:56:08 +00:00
switch_log_node_t * dnode = ( switch_log_node_t * ) pop ;
2010-02-06 03:38:24 +00:00
2008-12-20 14:56:08 +00:00
if ( dnode - > data ) {
2010-02-06 03:38:24 +00:00
switch_snprintf ( buf , sizeof ( buf ) ,
2008-12-20 14:56:08 +00:00
" Content-Type: log/data \n "
" Content-Length: % " SWITCH_SSIZE_T_FMT " \n "
" Log-Level: %d \n "
" Text-Channel: %d \n "
" Log-File: %s \n "
" Log-Func: %s \n "
2009-07-18 19:08:07 +00:00
" Log-Line: %d \n "
2009-08-13 20:35:02 +00:00
" User-Data: %s \n "
2008-12-20 14:56:08 +00:00
" \n " ,
strlen ( dnode - > data ) ,
2010-02-06 03:38:24 +00:00
dnode - > level , dnode - > channel , dnode - > file , dnode - > func , dnode - > line , switch_str_nil ( dnode - > userdata )
) ;
2006-10-13 14:32:38 +00:00
len = strlen ( buf ) ;
2006-07-25 14:14:07 +00:00
switch_socket_send ( listener - > sock , buf , & len ) ;
2008-12-20 14:56:08 +00:00
len = strlen ( dnode - > data ) ;
switch_socket_send ( listener - > sock , dnode - > data , & len ) ;
2006-07-25 14:14:07 +00:00
}
2010-02-06 03:38:24 +00:00
2009-08-22 19:26:58 +00:00
switch_log_node_free ( & dnode ) ;
2006-07-25 14:14:07 +00:00
do_sleep = 0 ;
}
}
2010-02-06 03:38:24 +00:00
2009-02-21 23:19:58 +00:00
if ( listener - > session ) {
2009-05-11 22:28:02 +00:00
switch_channel_t * chan = switch_core_session_get_channel ( listener - > session ) ;
if ( switch_channel_get_state ( chan ) < CS_HANGUP & & switch_channel_test_flag ( chan , CF_DIVERT_EVENTS ) ) {
2009-02-21 23:19:58 +00:00
switch_event_t * e = NULL ;
while ( switch_core_session_dequeue_event ( listener - > session , & e , SWITCH_TRUE ) = = SWITCH_STATUS_SUCCESS ) {
2011-01-25 20:13:15 +00:00
if ( switch_queue_trypush ( listener - > event_queue , e ) ! = SWITCH_STATUS_SUCCESS ) {
2009-02-21 23:19:58 +00:00
switch_core_session_queue_event ( listener - > session , & e ) ;
break ;
}
}
}
}
2006-07-25 14:14:07 +00:00
if ( switch_test_flag ( listener , LFLAG_EVENTS ) ) {
2009-01-15 22:11:27 +00:00
while ( switch_queue_trypop ( listener - > event_queue , & pop ) = = SWITCH_STATUS_SUCCESS ) {
2006-07-25 14:14:07 +00:00
char hbuf [ 512 ] ;
2007-12-16 03:01:50 +00:00
switch_event_t * pevent = ( switch_event_t * ) pop ;
2006-11-11 19:32:45 +00:00
char * etype ;
2010-02-06 03:38:24 +00:00
2006-07-25 14:14:07 +00:00
do_sleep = 0 ;
if ( listener - > format = = EVENT_FORMAT_PLAIN ) {
etype = " plain " ;
2007-12-16 03:01:50 +00:00
switch_event_serialize ( pevent , & listener - > ebuf , SWITCH_TRUE ) ;
2010-06-17 16:43:09 +00:00
} else if ( listener - > format = = EVENT_FORMAT_JSON ) {
etype = " json " ;
switch_event_serialize_json ( pevent , & listener - > ebuf ) ;
2006-07-25 14:14:07 +00:00
} else {
switch_xml_t xml ;
etype = " xml " ;
2010-08-14 22:39:49 +00:00
if ( ( xml = switch_event_xmlize ( pevent , SWITCH_VA_NONE ) ) ) {
2007-11-30 23:45:27 +00:00
listener - > ebuf = switch_xml_toxml ( xml , SWITCH_FALSE ) ;
2006-07-25 14:14:07 +00:00
switch_xml_free ( xml ) ;
} else {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( listener - > session ) , SWITCH_LOG_ERROR , " XML ERROR! \n " ) ;
2008-01-20 22:39:08 +00:00
goto endloop ;
2006-07-25 14:14:07 +00:00
}
}
2007-03-29 22:31:56 +00:00
2009-01-15 22:11:27 +00:00
switch_assert ( listener - > ebuf ) ;
2010-02-06 03:38:24 +00:00
2006-11-11 19:32:45 +00:00
len = strlen ( listener - > ebuf ) ;
2006-07-25 14:14:07 +00:00
2007-12-12 21:53:32 +00:00
switch_snprintf ( hbuf , sizeof ( hbuf ) , " Content-Length: % " SWITCH_SSIZE_T_FMT " \n " " Content-Type: text/event-%s \n " " \n " , len , etype ) ;
2006-07-25 14:14:07 +00:00
2006-10-13 14:32:38 +00:00
len = strlen ( hbuf ) ;
2006-07-25 14:14:07 +00:00
switch_socket_send ( listener - > sock , hbuf , & len ) ;
2006-11-11 19:32:45 +00:00
len = strlen ( listener - > ebuf ) ;
switch_socket_send ( listener - > sock , listener - > ebuf , & len ) ;
2010-02-06 03:38:24 +00:00
2006-11-11 19:32:45 +00:00
switch_safe_free ( listener - > ebuf ) ;
2008-05-27 04:54:52 +00:00
2010-02-06 03:38:24 +00:00
endloop :
2008-10-17 18:44:26 +00:00
2008-01-20 22:39:08 +00:00
switch_event_destroy ( & pevent ) ;
2006-07-25 14:14:07 +00:00
}
}
}
2009-01-15 22:11:27 +00:00
2017-01-06 07:10:15 +00:00
if ( switch_test_flag ( listener , LFLAG_HANDLE_DISCO ) & &
2012-04-13 13:43:46 +00:00
listener - > linger_timeout ! = ( time_t ) - 1 & & switch_epoch_time_now ( NULL ) > listener - > linger_timeout ) {
2011-12-08 18:25:52 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( listener - > session ) , SWITCH_LOG_DEBUG , " linger timeout, closing socket \n " ) ;
status = SWITCH_STATUS_FALSE ;
break ;
}
2009-02-25 03:41:18 +00:00
if ( channel & & switch_channel_down ( channel ) & & ! switch_test_flag ( listener , LFLAG_HANDLE_DISCO ) ) {
2009-01-16 15:32:10 +00:00
switch_set_flag_locked ( listener , LFLAG_HANDLE_DISCO ) ;
if ( switch_test_flag ( listener , LFLAG_LINGER ) ) {
char disco_buf [ 512 ] = " " ;
2017-01-06 07:10:15 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( listener - > session ) , SWITCH_LOG_DEBUG , " %s Socket Linger %d \n " ,
2012-05-10 17:23:00 +00:00
switch_channel_get_name ( channel ) , ( int ) listener - > linger_timeout ) ;
2017-01-06 07:10:15 +00:00
2012-05-03 19:23:09 +00:00
switch_snprintf ( disco_buf , sizeof ( disco_buf ) , " Content-Type: text/disconnect-notice \n "
" Controlled-Session-UUID: %s \n "
2017-01-06 07:10:15 +00:00
" Content-Disposition: linger \n "
2012-05-03 19:23:09 +00:00
" Channel-Name: %s \n "
2012-05-10 17:23:00 +00:00
" Linger-Time: %d \n "
2017-01-06 07:10:15 +00:00
" Content-Length: 0 \n \n " ,
2012-05-10 17:23:00 +00:00
switch_core_session_get_uuid ( listener - > session ) , switch_channel_get_name ( channel ) , ( int ) listener - > linger_timeout ) ;
2012-05-03 19:23:09 +00:00
2009-01-16 15:32:10 +00:00
2012-04-13 13:43:46 +00:00
if ( listener - > linger_timeout ! = ( time_t ) - 1 ) {
listener - > linger_timeout + = switch_epoch_time_now ( NULL ) ;
}
2017-01-06 07:10:15 +00:00
2009-01-16 15:32:10 +00:00
len = strlen ( disco_buf ) ;
switch_socket_send ( listener - > sock , disco_buf , & len ) ;
} else {
status = SWITCH_STATUS_FALSE ;
break ;
}
2009-01-15 22:11:27 +00:00
}
2010-02-06 03:38:24 +00:00
2006-07-25 14:14:07 +00:00
if ( do_sleep ) {
2012-06-26 14:58:51 +00:00
int fdr = 0 ;
switch_poll ( listener - > pollfd , 1 , & fdr , 20000 ) ;
} else {
switch_os_yield ( ) ;
2006-07-25 14:14:07 +00:00
}
}
2006-11-11 19:32:45 +00:00
2011-10-20 15:19:39 +00:00
end :
2011-11-17 17:47:14 +00:00
switch_safe_free ( mbuf ) ;
2006-07-25 14:14:07 +00:00
return status ;
}
2006-09-07 03:58:01 +00:00
struct api_command_struct {
char * api_cmd ;
char * arg ;
listener_t * listener ;
char uuid_str [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] ;
2009-02-07 16:44:46 +00:00
int bg ;
2019-08-22 19:35:34 +00:00
char bg_owner_uuid_str [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] ;
2009-02-07 16:44:46 +00:00
int ack ;
2010-01-20 17:45:53 +00:00
int console_execute ;
2007-09-29 01:06:08 +00:00
switch_memory_pool_t * pool ;
2006-09-07 03:58:01 +00:00
} ;
2008-05-27 04:54:52 +00:00
static void * SWITCH_THREAD_FUNC api_exec ( switch_thread_t * thread , void * obj )
2006-09-07 03:58:01 +00:00
{
struct api_command_struct * acs = ( struct api_command_struct * ) obj ;
2007-03-29 22:31:56 +00:00
switch_stream_handle_t stream = { 0 } ;
char * reply , * freply = NULL ;
switch_status_t status ;
2009-02-20 01:10:59 +00:00
switch_mutex_lock ( globals . listener_mutex ) ;
prefs . threads + + ;
switch_mutex_unlock ( globals . listener_mutex ) ;
2010-02-06 03:38:24 +00:00
2008-05-27 20:04:04 +00:00
if ( ! acs ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Internal error. \n " ) ;
2009-02-20 01:10:59 +00:00
goto cleanup ;
2008-05-27 20:04:04 +00:00
}
2009-02-07 16:44:46 +00:00
if ( ! acs - > listener | | ! switch_test_flag ( acs - > listener , LFLAG_RUNNING ) | |
! acs - > listener - > rwlock | | switch_thread_rwlock_tryrdlock ( acs - > listener - > rwlock ) ! = SWITCH_STATUS_SUCCESS ) {
2006-09-07 03:58:01 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error! cannot get read lock. \n " ) ;
2009-02-07 16:44:46 +00:00
acs - > ack = - 1 ;
2006-09-07 03:58:01 +00:00
goto done ;
}
2010-02-06 03:38:24 +00:00
2009-02-07 16:44:46 +00:00
acs - > ack = 1 ;
2010-02-06 03:38:24 +00:00
2006-09-07 03:58:01 +00:00
SWITCH_STANDARD_STREAM ( stream ) ;
2010-02-06 03:38:24 +00:00
2010-01-20 17:45:53 +00:00
if ( acs - > console_execute ) {
if ( ( status = switch_console_execute ( acs - > api_cmd , 0 , & stream ) ) ! = SWITCH_STATUS_SUCCESS ) {
2010-11-08 16:14:46 +00:00
stream . write_function ( & stream , " -ERR %s Command not found! \n " , acs - > api_cmd ) ;
2010-01-20 17:45:53 +00:00
}
} else {
status = switch_api_execute ( acs - > api_cmd , acs - > arg , NULL , & stream ) ;
}
if ( status = = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:31:56 +00:00
reply = stream . data ;
} else {
2010-11-08 16:14:46 +00:00
freply = switch_mprintf ( " -ERR %s Command not found! \n " , acs - > api_cmd ) ;
2007-03-29 22:31:56 +00:00
reply = freply ;
}
if ( ! reply ) {
reply = " Command returned no output! " ;
}
if ( acs - > bg ) {
switch_event_t * event ;
if ( switch_event_create ( & event , SWITCH_EVENT_BACKGROUND_JOB ) = = SWITCH_STATUS_SUCCESS ) {
2008-08-16 02:19:43 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Job-UUID " , acs - > uuid_str ) ;
2019-08-22 19:35:34 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Job-Owner-UUID " , acs - > bg_owner_uuid_str ) ;
2008-08-16 02:19:43 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Job-Command " , acs - > api_cmd ) ;
2008-01-18 15:43:57 +00:00
if ( acs - > arg ) {
2008-08-16 02:19:43 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Job-Command-Arg " , acs - > arg ) ;
2008-01-18 15:43:57 +00:00
}
2007-03-29 22:31:56 +00:00
switch_event_add_body ( event , " %s " , reply ) ;
switch_event_fire ( & event ) ;
}
} else {
switch_size_t rlen , blen ;
char buf [ 1024 ] = " " ;
2008-03-06 18:12:38 +00:00
if ( ! ( rlen = strlen ( reply ) ) ) {
reply = " -ERR no reply \n " ;
rlen = strlen ( reply ) ;
}
2007-12-12 21:53:32 +00:00
switch_snprintf ( buf , sizeof ( buf ) , " Content-Type: api/response \n Content-Length: % " SWITCH_SSIZE_T_FMT " \n \n " , rlen ) ;
2007-03-29 22:31:56 +00:00
blen = strlen ( buf ) ;
switch_socket_send ( acs - > listener - > sock , buf , & blen ) ;
switch_socket_send ( acs - > listener - > sock , reply , & rlen ) ;
}
switch_safe_free ( stream . data ) ;
switch_safe_free ( freply ) ;
2006-09-07 03:58:01 +00:00
2019-07-12 15:58:32 +00:00
switch_thread_rwlock_unlock ( acs - > listener - > rwlock ) ;
2007-03-29 22:31:56 +00:00
2008-05-27 04:54:52 +00:00
done :
2009-02-07 16:44:46 +00:00
2008-05-27 20:04:04 +00:00
if ( acs - > bg ) {
2007-09-29 01:06:08 +00:00
switch_memory_pool_t * pool = acs - > pool ;
2009-02-07 16:44:46 +00:00
if ( acs - > ack = = - 1 ) {
int sanity = 2000 ;
2010-02-06 03:38:24 +00:00
while ( acs - > ack = = - 1 ) {
2009-02-07 16:44:46 +00:00
switch_cond_next ( ) ;
2010-02-06 03:38:24 +00:00
if ( - - sanity < = 0 )
break ;
2009-02-07 16:44:46 +00:00
}
}
2007-09-29 01:06:08 +00:00
acs = NULL ;
switch_core_destroy_memory_pool ( & pool ) ;
pool = NULL ;
2010-02-06 03:38:24 +00:00
2006-09-07 03:58:01 +00:00
}
2009-02-07 16:44:46 +00:00
2010-02-06 03:38:24 +00:00
cleanup :
2009-02-20 01:10:59 +00:00
switch_mutex_lock ( globals . listener_mutex ) ;
prefs . threads - - ;
switch_mutex_unlock ( globals . listener_mutex ) ;
2006-09-07 03:58:01 +00:00
return NULL ;
2007-03-29 22:31:56 +00:00
2006-09-07 03:58:01 +00:00
}
2010-01-05 19:47:49 +00:00
static switch_bool_t auth_api_command ( listener_t * listener , const char * api_cmd , const char * arg )
{
const char * check_cmd = api_cmd ;
2010-02-25 19:02:42 +00:00
char * sneaky_commands [ ] = { " bgapi " , " sched_api " , " eval " , " expand " , " xml_wrap " , NULL } ;
2010-01-05 19:47:49 +00:00
int x = 0 ;
char * dup_arg = NULL ;
char * next = NULL ;
switch_bool_t ok = SWITCH_TRUE ;
2010-02-06 03:38:24 +00:00
top :
2017-01-06 07:10:15 +00:00
2010-01-05 19:47:49 +00:00
if ( ! switch_core_hash_find ( listener - > allowed_api_hash , check_cmd ) ) {
ok = SWITCH_FALSE ;
goto end ;
}
2010-02-06 03:38:24 +00:00
while ( check_cmd ) {
2010-01-05 19:47:49 +00:00
for ( x = 0 ; sneaky_commands [ x ] ; x + + ) {
if ( ! strcasecmp ( sneaky_commands [ x ] , check_cmd ) ) {
if ( check_cmd = = api_cmd ) {
if ( arg ) {
2010-08-18 14:20:59 +00:00
switch_safe_free ( dup_arg ) ;
2010-01-05 19:47:49 +00:00
dup_arg = strdup ( arg ) ;
2019-07-12 15:58:32 +00:00
switch_assert ( dup_arg ) ;
2010-01-05 19:47:49 +00: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 ;
}
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
if ( ( next = strchr ( check_cmd , ' ' ) ) ) {
* next + + = ' \0 ' ;
}
}
goto top ;
}
}
break ;
}
2010-02-06 03:38:24 +00:00
end :
2010-01-05 19:47:49 +00:00
switch_safe_free ( dup_arg ) ;
return ok ;
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
}
2015-09-21 23:00:14 +00:00
static void set_all_custom ( listener_t * listener )
{
switch_console_callback_match_t * events = NULL ;
switch_console_callback_match_node_t * m ;
if ( switch_event_get_custom_events ( & events ) = = SWITCH_STATUS_SUCCESS ) {
for ( m = events - > head ; m ; m = m - > next ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG1 , " ADDING CUSTOM EVENT: %s \n " , m - > val ) ;
switch_core_hash_insert ( listener - > event_hash , m - > val , MARKER ) ;
}
2017-01-06 07:10:15 +00:00
2015-09-21 23:00:14 +00:00
switch_console_free_matches ( & events ) ;
}
}
static void set_allowed_custom ( listener_t * listener )
{
switch_hash_index_t * hi = NULL ;
const void * var ;
void * val ;
switch_assert ( listener - > allowed_event_hash ) ;
2017-01-06 07:10:15 +00:00
2015-09-21 23:00:14 +00:00
for ( hi = switch_core_hash_first ( listener - > allowed_event_hash ) ; hi ; hi = switch_core_hash_next ( & hi ) ) {
switch_core_hash_this ( hi , & var , NULL , & val ) ;
switch_core_hash_insert ( listener - > event_hash , ( char * ) var , MARKER ) ;
}
}
2008-08-21 16:09:22 +00:00
static switch_status_t parse_command ( listener_t * listener , switch_event_t * * event , char * reply , uint32_t reply_len )
2006-07-22 21:49:52 +00:00
{
2006-07-25 14:14:07 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2014-01-03 18:43:42 +00:00
char * cmd = NULL ;
2009-02-27 20:21:48 +00:00
char unload_cheat [ ] = " api bgapi unload mod_event_socket " ;
char reload_cheat [ ] = " api bgapi reload mod_event_socket " ;
2010-02-06 03:38:24 +00:00
2006-07-22 21:49:52 +00:00
* reply = ' \0 ' ;
2014-01-03 18:43:42 +00:00
if ( ! event | | ! * event | | ! ( cmd = switch_event_get_header ( * event , " command " ) ) ) {
switch_clear_flag_locked ( listener , LFLAG_RUNNING ) ;
switch_snprintf ( reply , reply_len , " -ERR command parse error. " ) ;
goto done ;
}
2009-02-27 16:38:19 +00:00
if ( switch_stristr ( " unload " , cmd ) & & switch_stristr ( " mod_event_socket " , cmd ) ) {
2009-02-27 20:21:48 +00:00
cmd = unload_cheat ;
} else if ( switch_stristr ( " reload " , cmd ) & & switch_stristr ( " mod_event_socket " , cmd ) ) {
cmd = reload_cheat ;
2010-02-06 03:38:24 +00:00
}
2009-02-27 16:35:42 +00:00
2010-01-05 19:47:49 +00:00
if ( ! strncasecmp ( cmd , " exit " , 4 ) | | ! strncasecmp ( cmd , " ... " , 3 ) ) {
2006-07-22 21:49:52 +00:00
switch_clear_flag_locked ( listener , LFLAG_RUNNING ) ;
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " +OK bye " ) ;
2006-07-22 21:49:52 +00:00
goto done ;
}
if ( ! switch_test_flag ( listener , LFLAG_AUTHED ) ) {
if ( ! strncasecmp ( cmd , " auth " , 5 ) ) {
2006-07-22 22:16:06 +00:00
char * pass ;
2006-07-22 21:49:52 +00:00
strip_cr ( cmd ) ;
2006-07-22 22:16:06 +00:00
pass = cmd + 5 ;
2006-07-22 21:49:52 +00:00
if ( ! strcmp ( prefs . password , pass ) ) {
switch_set_flag_locked ( listener , LFLAG_AUTHED ) ;
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " +OK accepted " ) ;
2006-07-22 21:49:52 +00:00
} else {
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " -ERR invalid " ) ;
2006-07-22 21:49:52 +00:00
switch_clear_flag_locked ( listener , LFLAG_RUNNING ) ;
}
goto done ;
}
2010-01-05 19:47:49 +00:00
if ( ! strncasecmp ( cmd , " userauth " , 9 ) ) {
const char * passwd ;
const char * allowed_api ;
const char * allowed_events ;
switch_event_t * params ;
2011-12-28 05:35:05 +00:00
char * user = NULL , * domain_name = NULL , * pass = NULL ;
2010-01-05 19:47:49 +00:00
switch_xml_t x_domain = NULL , x_domain_root , x_user = NULL , x_params , x_param , x_group = NULL ;
int authed = 0 ;
char * edup = NULL ;
char event_reply [ 512 ] = " Allowed-Events: all \n " ;
char api_reply [ 512 ] = " Allowed-API: all \n " ;
char log_reply [ 512 ] = " " ;
int allowed_log = 1 ;
2011-01-12 21:32:05 +00:00
char * tmp ;
2010-01-05 19:47:49 +00:00
switch_clear_flag ( listener , LFLAG_ALLOW_LOG ) ;
strip_cr ( cmd ) ;
user = cmd + 9 ;
2019-07-12 15:58:32 +00:00
if ( ( domain_name = strchr ( user , ' @ ' ) ) ) {
2010-12-29 20:44:05 +00:00
* domain_name + + = ' \0 ' ;
}
2011-12-28 05:35:05 +00:00
if ( domain_name & & ( pass = strchr ( domain_name , ' : ' ) ) ) {
2010-12-29 19:59:12 +00:00
* pass + + = ' \0 ' ;
}
2010-12-29 20:13:06 +00:00
2011-01-12 21:32:05 +00:00
if ( ( tmp = strchr ( user , ' : ' ) ) ) {
* tmp + + = ' \0 ' ;
pass = tmp ;
2010-12-29 20:13:06 +00:00
}
2017-01-06 07:10:15 +00:00
2010-01-05 19:47:49 +00:00
if ( zstr ( user ) | | zstr ( domain_name ) ) {
switch_snprintf ( reply , reply_len , " -ERR invalid " ) ;
switch_clear_flag_locked ( listener , LFLAG_RUNNING ) ;
goto done ;
}
passwd = NULL ;
allowed_events = NULL ;
allowed_api = NULL ;
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
params = NULL ;
x_domain_root = NULL ;
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
switch_event_create ( & params , SWITCH_EVENT_REQUEST_PARAMS ) ;
switch_assert ( params ) ;
switch_event_add_header_string ( params , SWITCH_STACK_BOTTOM , " action " , " event_socket_auth " ) ;
if ( switch_xml_locate_user ( " id " , user , domain_name , NULL , & x_domain_root , & x_domain , & x_user , & x_group , params ) = = SWITCH_STATUS_SUCCESS ) {
switch_xml_t list [ 3 ] ;
int x = 0 ;
list [ 0 ] = x_domain ;
list [ 1 ] = x_group ;
list [ 2 ] = x_user ;
2010-02-06 03:38:24 +00:00
for ( x = 0 ; x < 3 ; x + + ) {
2010-01-05 19:47:49 +00:00
if ( ( x_params = switch_xml_child ( list [ x ] , " 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 " ) ;
if ( ! strcasecmp ( var , " esl-password " ) ) {
passwd = val ;
} else if ( ! strcasecmp ( var , " esl-allowed-log " ) ) {
allowed_log = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " esl-allowed-events " ) ) {
allowed_events = val ;
} else if ( ! strcasecmp ( var , " esl-allowed-api " ) ) {
allowed_api = val ;
}
}
}
}
} else {
authed = 0 ;
goto bot ;
}
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
if ( ! zstr ( passwd ) & & ! zstr ( pass ) & & ! strcmp ( passwd , pass ) ) {
authed = 1 ;
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
if ( allowed_events ) {
char delim = ' , ' ;
char * cur , * next ;
int count = 0 , custom = 0 , key_count = 0 ;
switch_set_flag ( listener , LFLAG_AUTH_EVENTS ) ;
switch_snprintf ( event_reply , sizeof ( event_reply ) , " Allowed-Events: %s \n " , allowed_events ) ;
2014-03-08 19:37:09 +00:00
switch_core_hash_init ( & listener - > allowed_event_hash ) ;
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
edup = strdup ( allowed_events ) ;
2019-07-12 15:58:32 +00:00
switch_assert ( edup ) ;
2010-01-05 19:47:49 +00:00
if ( strchr ( edup , ' ' ) ) {
delim = ' ' ;
}
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
for ( cur = edup ; cur ; count + + ) {
switch_event_types_t type ;
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
if ( ( next = strchr ( cur , delim ) ) ) {
* next + + = ' \0 ' ;
}
2010-01-06 16:59:53 +00:00
2010-01-05 19:47:49 +00:00
if ( custom ) {
switch_core_hash_insert ( listener - > allowed_event_hash , cur , MARKER ) ;
} else if ( switch_name_event ( cur , & type ) = = SWITCH_STATUS_SUCCESS ) {
key_count + + ;
if ( type = = SWITCH_EVENT_ALL ) {
uint32_t x = 0 ;
switch_set_flag ( listener , LFLAG_ALL_EVENTS_AUTHED ) ;
for ( x = 0 ; x < SWITCH_EVENT_ALL ; x + + ) {
listener - > allowed_event_list [ x ] = 1 ;
}
}
if ( type < = SWITCH_EVENT_ALL ) {
listener - > allowed_event_list [ type ] = 1 ;
}
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
if ( type = = SWITCH_EVENT_CUSTOM ) {
custom + + ;
}
}
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
cur = next ;
}
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
switch_safe_free ( edup ) ;
}
switch_snprintf ( log_reply , sizeof ( log_reply ) , " Allowed-LOG: %s \n " , allowed_log ? " true " : " false " ) ;
if ( allowed_log ) {
switch_set_flag ( listener , LFLAG_ALLOW_LOG ) ;
}
if ( allowed_api ) {
char delim = ' , ' ;
char * cur , * next ;
int count = 0 ;
switch_snprintf ( api_reply , sizeof ( api_reply ) , " Allowed-API: %s \n " , allowed_api ) ;
2014-03-08 19:37:09 +00:00
switch_core_hash_init ( & listener - > allowed_api_hash ) ;
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
edup = strdup ( allowed_api ) ;
if ( strchr ( edup , ' ' ) ) {
delim = ' ' ;
}
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
for ( cur = edup ; cur ; count + + ) {
if ( ( next = strchr ( cur , delim ) ) ) {
* next + + = ' \0 ' ;
}
switch_core_hash_insert ( listener - > allowed_api_hash , cur , MARKER ) ;
cur = next ;
}
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
switch_safe_free ( edup ) ;
}
}
2010-02-06 03:38:24 +00:00
bot :
2019-07-12 15:58:32 +00:00
switch_event_destroy ( & params ) ;
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
if ( authed ) {
switch_set_flag_locked ( listener , LFLAG_AUTHED ) ;
switch_snprintf ( reply , reply_len , " ~Reply-Text: +OK accepted \n %s%s%s \n " , event_reply , api_reply , log_reply ) ;
} else {
switch_snprintf ( reply , reply_len , " -ERR invalid " ) ;
switch_clear_flag_locked ( listener , LFLAG_RUNNING ) ;
}
2010-02-06 03:38:24 +00:00
2010-01-05 19:47:49 +00:00
if ( x_domain_root ) {
switch_xml_free ( x_domain_root ) ;
2010-02-06 03:38:24 +00:00
}
2010-01-05 19:47:49 +00:00
}
2006-07-22 21:49:52 +00:00
goto done ;
}
2006-09-22 13:52:36 +00:00
2008-10-30 00:39:55 +00:00
if ( ! strncasecmp ( cmd , " filter " , 7 ) ) {
char * header_name = cmd + 7 ;
2010-01-28 01:00:04 +00:00
char * header_val = NULL ;
2008-10-30 00:39:55 +00:00
strip_cr ( header_name ) ;
2010-02-06 03:38:24 +00:00
while ( header_name & & * header_name & & * header_name = = ' ' )
header_name + + ;
2010-01-28 01:00:04 +00:00
if ( ( header_val = strchr ( header_name , ' ' ) ) ) {
* header_val + + = ' \0 ' ;
2008-10-30 00:39:55 +00:00
}
2010-02-06 03:38:24 +00:00
switch_mutex_lock ( listener - > filter_mutex ) ;
2008-10-30 00:39:55 +00:00
if ( ! listener - > filters ) {
2010-11-22 23:06:59 +00:00
switch_event_create_plain ( & listener - > filters , SWITCH_EVENT_CLONE ) ;
2011-02-14 16:50:14 +00:00
switch_clear_flag ( listener - > filters , EF_UNIQ_HEADERS ) ;
2008-10-30 00:39:55 +00:00
}
2010-02-06 03:38:24 +00:00
2010-02-04 15:50:04 +00:00
if ( ! strcasecmp ( header_name , " delete " ) & & header_val ) {
2010-01-28 01:00:04 +00:00
header_name = header_val ;
if ( ( header_val = strchr ( header_name , ' ' ) ) ) {
* header_val + + = ' \0 ' ;
}
if ( ! strcasecmp ( header_name , " all " ) ) {
2008-10-30 00:39:55 +00:00
switch_event_destroy ( & listener - > filters ) ;
2010-11-22 23:06:59 +00:00
switch_event_create_plain ( & listener - > filters , SWITCH_EVENT_CLONE ) ;
2008-10-30 00:39:55 +00:00
} else {
2010-01-28 01:00:04 +00:00
switch_event_del_header_val ( listener - > filters , header_name , header_val ) ;
}
switch_snprintf ( reply , reply_len , " +OK filter deleted. [%s][%s] " , header_name , switch_str_nil ( header_val ) ) ;
} else if ( header_val ) {
if ( ! strcasecmp ( header_name , " add " ) ) {
header_name = header_val ;
if ( ( header_val = strchr ( header_name , ' ' ) ) ) {
* header_val + + = ' \0 ' ;
}
2008-10-30 00:39:55 +00:00
}
switch_event_add_header_string ( listener - > filters , SWITCH_STACK_BOTTOM , header_name , header_val ) ;
switch_snprintf ( reply , reply_len , " +OK filter added. [%s]=[%s] " , header_name , header_val ) ;
2010-01-28 01:00:04 +00:00
} else {
switch_snprintf ( reply , reply_len , " -ERR invalid syntax " ) ;
2008-10-30 00:39:55 +00:00
}
switch_mutex_unlock ( listener - > filter_mutex ) ;
goto done ;
}
2010-02-06 03:38:24 +00:00
2009-04-30 22:45:46 +00:00
if ( listener - > session & & ! strncasecmp ( cmd , " resume " , 6 ) ) {
2010-02-06 03:38:24 +00:00
switch_set_flag_locked ( listener , LFLAG_RESUME ) ;
2009-04-30 22:45:46 +00:00
switch_channel_set_variable ( switch_core_session_get_channel ( listener - > session ) , " socket_resume " , " true " ) ;
switch_snprintf ( reply , reply_len , " +OK " ) ;
goto done ;
}
2006-09-22 13:52:36 +00:00
2008-10-22 16:32:55 +00:00
if ( listener - > session | | ! strncasecmp ( cmd , " myevents " , 9 ) ) {
switch_channel_t * channel = NULL ;
if ( listener - > session ) {
channel = switch_core_session_get_channel ( listener - > session ) ;
}
2007-03-29 22:31:56 +00:00
if ( ! strncasecmp ( cmd , " connect " , 7 ) ) {
2009-03-23 19:53:57 +00:00
switch_event_t * call_event ;
char * event_str ;
switch_size_t len ;
2009-04-30 22:45:46 +00:00
2010-02-06 03:38:24 +00:00
switch_set_flag_locked ( listener , LFLAG_CONNECTED ) ;
2009-03-23 19:53:57 +00:00
switch_event_create ( & call_event , SWITCH_EVENT_CHANNEL_DATA ) ;
2010-02-06 03:38:24 +00:00
2009-05-11 22:28:02 +00:00
if ( channel ) {
switch_caller_profile_event_set_data ( switch_channel_get_caller_profile ( channel ) , " Channel " , call_event ) ;
switch_channel_event_set_data ( channel , call_event ) ;
}
2009-03-23 19:53:57 +00:00
switch_event_add_header_string ( call_event , SWITCH_STACK_BOTTOM , " Content-Type " , " command/reply " ) ;
switch_event_add_header_string ( call_event , SWITCH_STACK_BOTTOM , " Reply-Text " , " +OK \n " ) ;
switch_event_add_header_string ( call_event , SWITCH_STACK_BOTTOM , " Socket-Mode " , switch_test_flag ( listener , LFLAG_ASYNC ) ? " async " : " static " ) ;
switch_event_add_header_string ( call_event , SWITCH_STACK_BOTTOM , " Control " , switch_test_flag ( listener , LFLAG_FULL ) ? " full " : " single-channel " ) ;
switch_event_serialize ( call_event , & event_str , SWITCH_TRUE ) ;
switch_assert ( event_str ) ;
len = strlen ( event_str ) ;
switch_socket_send ( listener - > sock , event_str , & len ) ;
switch_safe_free ( event_str ) ;
2009-09-16 21:23:00 +00:00
switch_event_destroy ( & call_event ) ;
2009-03-23 19:53:57 +00:00
//switch_snprintf(reply, reply_len, "+OK");
goto done_noreply ;
2007-03-29 22:31:56 +00:00
} else if ( ! strncasecmp ( cmd , " getvar " , 6 ) ) {
char * arg ;
2007-11-01 11:28:26 +00:00
const char * val = " " ;
2007-03-29 22:31:56 +00:00
strip_cr ( cmd ) ;
if ( ( arg = strchr ( cmd , ' ' ) ) ) {
* arg + + = ' \0 ' ;
if ( ! ( val = switch_channel_get_variable ( channel , arg ) ) ) {
val = " " ;
}
}
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " %s " , val ) ;
2007-03-29 22:31:56 +00:00
goto done ;
} else if ( ! strncasecmp ( cmd , " myevents " , 8 ) ) {
2008-10-22 16:32:55 +00:00
if ( switch_test_flag ( listener , LFLAG_MYEVENTS ) ) {
switch_snprintf ( reply , reply_len , " -ERR aready enabled. " ) ;
goto done ;
}
if ( ! listener - > session ) {
char * uuid ;
2010-02-06 03:38:24 +00:00
2008-10-22 16:32:55 +00:00
if ( ( uuid = cmd + 9 ) ) {
2011-09-09 19:31:02 +00:00
char * fmt ;
2008-10-22 16:32:55 +00:00
strip_cr ( uuid ) ;
2017-01-06 07:10:15 +00:00
2011-09-09 19:31:02 +00:00
if ( ( fmt = strchr ( uuid , ' ' ) ) ) {
* fmt + + = ' \0 ' ;
}
2017-01-06 07:10:15 +00:00
2008-10-22 16:32:55 +00:00
if ( ! ( listener - > session = switch_core_session_locate ( uuid ) ) ) {
2011-09-09 19:31:02 +00:00
if ( fmt ) {
switch_snprintf ( reply , reply_len , " -ERR invalid uuid " ) ;
goto done ;
}
}
if ( ( fmt = strchr ( uuid , ' ' ) ) ) {
if ( ! strcasecmp ( fmt , " xml " ) ) {
listener - > format = EVENT_FORMAT_XML ;
} else if ( ! strcasecmp ( fmt , " plain " ) ) {
listener - > format = EVENT_FORMAT_PLAIN ;
} else if ( ! strcasecmp ( fmt , " json " ) ) {
listener - > format = EVENT_FORMAT_JSON ;
2017-01-06 07:10:15 +00:00
}
2008-10-22 16:32:55 +00:00
}
switch_set_flag_locked ( listener , LFLAG_SESSION ) ;
switch_set_flag_locked ( listener , LFLAG_ASYNC ) ;
}
2010-02-06 03:38:24 +00:00
2008-10-22 16:32:55 +00:00
}
2008-10-27 15:10:22 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_ANSWER ] = 1 ;
listener - > event_list [ SWITCH_EVENT_CHANNEL_APPLICATION ] = 1 ;
listener - > event_list [ SWITCH_EVENT_CHANNEL_BRIDGE ] = 1 ;
2007-03-29 22:31:56 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_CREATE ] = 1 ;
2008-10-27 15:10:22 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_DATA ] = 1 ;
2007-03-29 22:31:56 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_DESTROY ] = 1 ;
listener - > event_list [ SWITCH_EVENT_CHANNEL_EXECUTE ] = 1 ;
2007-06-23 05:41:07 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE ] = 1 ;
2008-10-27 15:10:22 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_HANGUP ] = 1 ;
2009-09-29 02:23:08 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE ] = 1 ;
2008-10-27 15:10:22 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_ORIGINATE ] = 1 ;
2008-11-04 16:46:33 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_UUID ] = 1 ;
2007-03-29 22:31:56 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_OUTGOING ] = 1 ;
listener - > event_list [ SWITCH_EVENT_CHANNEL_PARK ] = 1 ;
2008-10-27 15:10:22 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_PROGRESS ] = 1 ;
listener - > event_list [ SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA ] = 1 ;
listener - > event_list [ SWITCH_EVENT_CHANNEL_STATE ] = 1 ;
listener - > event_list [ SWITCH_EVENT_CHANNEL_UNBRIDGE ] = 1 ;
2007-03-29 22:31:56 +00:00
listener - > event_list [ SWITCH_EVENT_CHANNEL_UNPARK ] = 1 ;
2008-10-27 15:10:22 +00:00
listener - > event_list [ SWITCH_EVENT_DETECTED_SPEECH ] = 1 ;
2007-03-29 22:31:56 +00:00
listener - > event_list [ SWITCH_EVENT_DTMF ] = 1 ;
listener - > event_list [ SWITCH_EVENT_NOTALK ] = 1 ;
2008-10-27 15:10:22 +00:00
listener - > event_list [ SWITCH_EVENT_TALK ] = 1 ;
2007-03-29 22:31:56 +00:00
switch_set_flag_locked ( listener , LFLAG_MYEVENTS ) ;
switch_set_flag_locked ( listener , LFLAG_EVENTS ) ;
if ( strstr ( cmd , " xml " ) | | strstr ( cmd , " XML " ) ) {
listener - > format = EVENT_FORMAT_XML ;
}
2010-06-17 16:43:09 +00:00
if ( strstr ( cmd , " json " ) | | strstr ( cmd , " JSON " ) ) {
listener - > format = EVENT_FORMAT_JSON ;
}
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " +OK Events Enabled " ) ;
2007-03-29 22:31:56 +00:00
goto done ;
}
}
2007-01-06 17:06:18 +00:00
2007-12-03 16:06:47 +00:00
2009-02-21 23:19:58 +00:00
if ( ! strncasecmp ( cmd , " divert_events " , 13 ) ) {
char * onoff = cmd + 13 ;
switch_channel_t * channel ;
2010-02-06 03:38:24 +00:00
2009-02-21 23:19:58 +00:00
if ( ! listener - > session ) {
switch_snprintf ( reply , reply_len , " -ERR not controlling a session. " ) ;
goto done ;
}
channel = switch_core_session_get_channel ( listener - > session ) ;
2010-02-06 03:38:24 +00:00
2019-07-12 15:58:32 +00:00
while ( * onoff = = ' ' ) {
onoff + + ;
}
2010-02-06 03:38:24 +00:00
2019-07-12 15:58:32 +00:00
if ( * onoff = = ' \r ' | | * onoff = = ' \n ' ) {
onoff = NULL ;
} else {
strip_cr ( onoff ) ;
2009-02-21 23:19:58 +00:00
}
2009-10-23 16:03:42 +00:00
if ( zstr ( onoff ) ) {
2009-02-21 23:19:58 +00:00
switch_snprintf ( reply , reply_len , " -ERR missing value. " ) ;
goto done ;
}
2010-02-06 03:38:24 +00:00
2009-02-21 23:19:58 +00:00
if ( ! strcasecmp ( onoff , " on " ) ) {
switch_snprintf ( reply , reply_len , " +OK events diverted " ) ;
switch_channel_set_flag ( channel , CF_DIVERT_EVENTS ) ;
} else {
switch_snprintf ( reply , reply_len , " +OK events not diverted " ) ;
switch_channel_clear_flag ( channel , CF_DIVERT_EVENTS ) ;
}
goto done ;
}
2008-12-12 15:44:37 +00:00
if ( ! strncasecmp ( cmd , " sendmsg " , 7 ) ) {
2006-09-07 03:58:01 +00:00
switch_core_session_t * session ;
2008-12-12 15:44:37 +00:00
char * uuid = cmd + 7 ;
2009-03-24 18:01:58 +00:00
const char * async_var = switch_event_get_header ( * event , " async " ) ;
int async = switch_test_flag ( listener , LFLAG_ASYNC ) ;
2010-02-06 03:38:24 +00:00
2009-03-24 18:01:58 +00:00
if ( switch_true ( async_var ) ) {
async = 1 ;
}
2010-02-06 03:38:24 +00:00
2019-07-12 15:58:32 +00:00
while ( * uuid = = ' ' ) {
uuid + + ;
}
2006-10-19 19:09:51 +00:00
2019-07-12 15:58:32 +00:00
if ( * uuid = = ' \r ' | | * uuid = = ' \n ' ) {
uuid = NULL ;
} else {
strip_cr ( uuid ) ;
2006-09-07 03:58:01 +00:00
}
2010-02-06 03:38:24 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( uuid ) ) {
2008-08-21 16:09:22 +00:00
uuid = switch_event_get_header ( * event , " session-id " ) ;
2006-09-07 03:58:01 +00:00
}
2008-12-12 15:44:37 +00:00
2009-03-24 18:01:58 +00:00
if ( uuid & & listener - > session & & ! strcmp ( uuid , switch_core_session_get_uuid ( listener - > session ) ) ) {
uuid = NULL ;
}
2009-02-17 14:13:32 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( uuid ) & & listener - > session ) {
2009-02-17 14:13:32 +00:00
if ( async ) {
2009-12-10 01:29:02 +00:00
if ( ( status = switch_core_session_queue_private_event ( listener - > session , event , SWITCH_FALSE ) ) = = SWITCH_STATUS_SUCCESS ) {
2008-12-08 16:08:37 +00:00
switch_snprintf ( reply , reply_len , " +OK " ) ;
} else {
switch_snprintf ( reply , reply_len , " -ERR memory error " ) ;
}
2006-09-07 03:58:01 +00:00
} else {
2008-12-08 16:08:37 +00:00
switch_ivr_parse_event ( listener - > session , * event ) ;
switch_snprintf ( reply , reply_len , " +OK " ) ;
2006-09-07 03:58:01 +00:00
}
} else {
2009-10-23 16:03:42 +00:00
if ( ! zstr ( uuid ) & & ( session = switch_core_session_locate ( uuid ) ) ) {
2009-12-10 01:29:02 +00:00
if ( ( status = switch_core_session_queue_private_event ( session , event , SWITCH_FALSE ) ) = = SWITCH_STATUS_SUCCESS ) {
2008-12-08 16:08:37 +00:00
switch_snprintf ( reply , reply_len , " +OK " ) ;
} else {
switch_snprintf ( reply , reply_len , " -ERR memory error " ) ;
}
switch_core_session_rwunlock ( session ) ;
} else {
switch_snprintf ( reply , reply_len , " -ERR invalid session id [%s] " , switch_str_nil ( uuid ) ) ;
}
2006-09-07 03:58:01 +00:00
}
2010-02-06 03:38:24 +00:00
2006-09-07 03:58:01 +00:00
goto done ;
2007-03-29 22:31:56 +00:00
2008-12-12 15:44:37 +00:00
}
2010-02-06 03:38:24 +00:00
2008-12-12 15:44:37 +00:00
if ( switch_test_flag ( listener , LFLAG_OUTBOUND ) & & ! switch_test_flag ( listener , LFLAG_FULL ) ) {
goto done ;
}
if ( ! strncasecmp ( cmd , " sendevent " , 9 ) ) {
char * ename ;
2009-09-15 19:18:20 +00:00
const char * uuid = NULL ;
2012-07-02 19:55:45 +00:00
char uuid_str [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] ;
switch_uuid_str ( uuid_str , sizeof ( uuid_str ) ) ;
2017-01-06 07:10:15 +00:00
2012-07-02 19:55:45 +00:00
switch_event_add_header_string ( * event , SWITCH_STACK_BOTTOM , " Event-UUID " , uuid_str ) ;
2009-09-15 19:18:20 +00:00
2008-12-12 15:44:37 +00:00
strip_cr ( cmd ) ;
ename = cmd + 9 ;
while ( ename & & ( * ename = = ' \t ' | | * ename = = ' ' ) ) {
+ + ename ;
}
if ( ename & & ( * ename = = ' \r ' | | * ename = = ' \n ' ) ) {
ename = NULL ;
}
if ( ename ) {
switch_event_types_t etype ;
if ( switch_name_event ( ename , & etype ) = = SWITCH_STATUS_SUCCESS ) {
2009-07-24 20:13:36 +00:00
const char * subclass_name = switch_event_get_header ( * event , " Event-Subclass " ) ;
2008-12-12 15:44:37 +00:00
( * event ) - > event_id = etype ;
2009-07-24 20:13:36 +00:00
if ( etype = = SWITCH_EVENT_CUSTOM & & subclass_name ) {
switch_event_set_subclass_name ( * event , subclass_name ) ;
}
2008-12-12 15:44:37 +00:00
}
}
2009-09-15 19:18:20 +00:00
if ( ( uuid = switch_event_get_header ( * event , " unique-id " ) ) ) {
switch_core_session_t * dsession ;
2012-07-02 19:55:45 +00:00
2009-09-15 19:18:20 +00:00
if ( ( dsession = switch_core_session_locate ( uuid ) ) ) {
switch_core_session_queue_event ( dsession , event ) ;
switch_core_session_rwunlock ( dsession ) ;
}
}
2010-02-06 03:38:24 +00:00
2009-09-15 19:18:20 +00:00
if ( * event ) {
2012-08-06 16:20:27 +00:00
switch_event_prep_for_delivery ( * event ) ;
2009-09-15 19:18:20 +00:00
switch_event_fire ( event ) ;
}
2012-07-02 19:55:45 +00:00
switch_snprintf ( reply , reply_len , " +OK %s " , uuid_str ) ;
2008-12-12 15:44:37 +00:00
goto done ;
2006-09-07 03:58:01 +00:00
} else if ( ! strncasecmp ( cmd , " api " , 4 ) ) {
2007-03-29 22:31:56 +00:00
struct api_command_struct acs = { 0 } ;
2010-01-20 17:45:53 +00:00
char * console_execute = switch_event_get_header ( * event , " console_execute " ) ;
2010-02-06 03:38:24 +00:00
2006-07-22 21:49:52 +00:00
char * api_cmd = cmd + 4 ;
2006-09-07 03:58:01 +00:00
char * arg = NULL ;
strip_cr ( api_cmd ) ;
2006-07-22 21:49:52 +00:00
2010-12-29 20:44:05 +00:00
if ( listener - > allowed_api_hash ) {
char * api_copy = strdup ( api_cmd ) ;
char * arg_copy = NULL ;
int ok = 0 ;
2019-07-12 15:58:32 +00:00
switch_assert ( api_copy ) ;
2010-12-29 20:44:05 +00:00
if ( ( arg_copy = strchr ( api_copy , ' ' ) ) ) {
* arg_copy + + = ' \0 ' ;
2010-01-20 17:45:53 +00:00
}
2017-01-06 07:10:15 +00:00
2010-12-29 20:44:05 +00:00
ok = auth_api_command ( listener , api_copy , arg_copy ) ;
free ( api_copy ) ;
2006-07-22 21:49:52 +00:00
2010-12-29 20:44:05 +00:00
if ( ! ok ) {
2010-01-05 19:47:49 +00:00
switch_snprintf ( reply , reply_len , " -ERR permission denied " ) ;
status = SWITCH_STATUS_SUCCESS ;
goto done ;
}
}
2017-01-06 07:10:15 +00:00
2010-12-29 20:44:05 +00:00
if ( ! ( acs . console_execute = switch_true ( console_execute ) ) ) {
if ( ( arg = strchr ( api_cmd , ' ' ) ) ) {
* arg + + = ' \0 ' ;
}
}
2017-01-06 07:10:15 +00:00
2006-09-07 03:58:01 +00:00
acs . listener = listener ;
acs . api_cmd = api_cmd ;
acs . arg = arg ;
acs . bg = 0 ;
2010-02-06 03:38:24 +00:00
2006-09-07 03:58:01 +00:00
api_exec ( NULL , ( void * ) & acs ) ;
2006-07-22 21:49:52 +00:00
2008-08-21 16:09:22 +00:00
status = SWITCH_STATUS_SUCCESS ;
goto done_noreply ;
2006-09-07 03:58:01 +00:00
} else if ( ! strncasecmp ( cmd , " bgapi " , 6 ) ) {
2007-09-29 01:06:08 +00:00
struct api_command_struct * acs = NULL ;
2006-09-07 03:58:01 +00:00
char * api_cmd = cmd + 6 ;
char * arg = NULL ;
2007-03-29 22:31:56 +00:00
char * uuid_str = NULL ;
2007-09-29 01:06:08 +00:00
switch_memory_pool_t * pool ;
switch_thread_t * thread ;
switch_threadattr_t * thd_attr = NULL ;
switch_uuid_t uuid ;
2009-02-07 16:44:46 +00:00
int sanity ;
2007-09-29 01:06:08 +00:00
2006-07-22 21:49:52 +00:00
strip_cr ( api_cmd ) ;
if ( ( arg = strchr ( api_cmd , ' ' ) ) ) {
* arg + + = ' \0 ' ;
}
2010-01-05 19:47:49 +00:00
if ( listener - > allowed_api_hash ) {
if ( ! auth_api_command ( listener , api_cmd , arg ) ) {
switch_snprintf ( reply , reply_len , " -ERR permission denied " ) ;
status = SWITCH_STATUS_SUCCESS ;
goto done ;
}
}
2007-09-29 01:06:08 +00:00
switch_core_new_memory_pool ( & pool ) ;
acs = switch_core_alloc ( pool , sizeof ( * acs ) ) ;
2007-12-16 03:01:50 +00:00
switch_assert ( acs ) ;
2007-09-29 01:06:08 +00:00
acs - > pool = pool ;
acs - > listener = listener ;
2010-01-20 17:45:53 +00:00
acs - > console_execute = 0 ;
2019-07-12 15:58:32 +00:00
acs - > api_cmd = switch_core_strdup ( acs - > pool , api_cmd ) ;
2007-09-29 01:06:08 +00:00
if ( arg ) {
acs - > arg = switch_core_strdup ( acs - > pool , arg ) ;
}
acs - > bg = 1 ;
2008-04-14 16:18:49 +00:00
2007-09-29 01:06:08 +00:00
switch_threadattr_create ( & thd_attr , acs - > pool ) ;
switch_threadattr_detach_set ( thd_attr , 1 ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
2008-04-14 16:18:49 +00:00
2008-08-21 16:09:22 +00:00
if ( ( uuid_str = switch_event_get_header ( * event , " job-uuid " ) ) ) {
2007-09-29 01:06:08 +00:00
switch_copy_string ( acs - > uuid_str , uuid_str , sizeof ( acs - > uuid_str ) ) ;
2006-09-07 03:58:01 +00:00
} else {
2007-09-29 01:06:08 +00:00
switch_uuid_get ( & uuid ) ;
switch_uuid_format ( acs - > uuid_str , & uuid ) ;
2006-09-07 03:58:01 +00:00
}
2019-08-22 19:35:34 +00:00
switch_copy_string ( acs - > bg_owner_uuid_str , switch_core_session_get_uuid ( listener - > session ) , sizeof ( acs - > bg_owner_uuid_str ) ) ;
2008-06-06 16:14:29 +00:00
switch_snprintf ( reply , reply_len , " ~Reply-Text: +OK Job-UUID: %s \n Job-UUID: %s \n \n " , acs - > uuid_str , acs - > uuid_str ) ;
2008-04-14 16:18:49 +00:00
switch_thread_create ( & thread , thd_attr , api_exec , acs , acs - > pool ) ;
2009-02-07 16:44:46 +00:00
sanity = 2000 ;
2010-02-06 03:38:24 +00:00
while ( ! acs - > ack ) {
2009-02-07 16:44:46 +00:00
switch_cond_next ( ) ;
2010-02-06 03:38:24 +00:00
if ( - - sanity < = 0 )
break ;
2009-02-07 16:44:46 +00:00
}
if ( acs - > ack = = - 1 ) {
acs - > ack - - ;
}
2008-05-27 04:54:52 +00:00
2008-08-21 16:09:22 +00:00
status = SWITCH_STATUS_SUCCESS ;
goto done_noreply ;
2006-07-22 21:49:52 +00:00
} else if ( ! strncasecmp ( cmd , " log " , 3 ) ) {
2017-05-08 19:01:56 +00:00
char * level_s , * p ;
2007-12-10 19:16:50 +00:00
switch_log_level_t ltype = SWITCH_LOG_DEBUG ;
2006-10-19 18:52:46 +00:00
2010-01-05 19:47:49 +00:00
if ( ! switch_test_flag ( listener , LFLAG_ALLOW_LOG ) ) {
switch_snprintf ( reply , reply_len , " -ERR permission denied " ) ;
goto done ;
}
2006-10-19 18:52:46 +00:00
//pull off the first newline/carriage return
2006-07-22 21:49:52 +00:00
strip_cr ( cmd ) ;
2007-03-29 22:31:56 +00:00
2006-10-19 18:52:46 +00:00
//move past the command
level_s = cmd + 3 ;
2006-07-22 21:49:52 +00:00
2017-05-08 19:01:56 +00:00
while ( * level_s = = ' ' ) {
2006-10-19 18:52:46 +00:00
level_s + + ;
}
2017-05-08 19:01:56 +00:00
if ( ( p = strchr ( level_s , ' ' ) ) ) {
* p = ' \0 ' ;
}
2006-10-19 18:52:46 +00:00
//see if we lined up on an argument or not
2009-10-23 16:03:42 +00:00
if ( ! zstr ( level_s ) ) {
2007-12-10 19:16:50 +00:00
ltype = switch_log_str2level ( level_s ) ;
2006-07-22 21:49:52 +00:00
}
2008-12-31 19:07:20 +00:00
if ( ltype ! = SWITCH_LOG_INVALID ) {
2007-12-10 19:16:50 +00:00
listener - > level = ltype ;
2006-07-22 21:49:52 +00:00
switch_set_flag ( listener , LFLAG_LOG ) ;
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " +OK log level %s [%d] " , level_s , listener - > level ) ;
2006-07-22 21:49:52 +00:00
} else {
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " -ERR invalid log level " ) ;
2006-07-22 21:49:52 +00:00
}
2009-01-16 15:32:10 +00:00
} else if ( ! strncasecmp ( cmd , " linger " , 6 ) ) {
if ( listener - > session ) {
2012-04-13 13:43:46 +00:00
time_t linger_time = 600 ; /* sounds reasonable? */
2011-12-08 18:25:52 +00:00
if ( * ( cmd + 6 ) = = ' ' & & * ( cmd + 7 ) ) { /*how long do you want to linger?*/
2012-04-13 13:43:46 +00:00
linger_time = ( time_t ) atoi ( cmd + 7 ) ;
} else {
linger_time = ( time_t ) - 1 ;
2011-12-08 18:25:52 +00:00
}
2012-04-13 13:43:46 +00:00
listener - > linger_timeout = linger_time ;
2009-01-16 15:32:10 +00:00
switch_set_flag_locked ( listener , LFLAG_LINGER ) ;
2012-04-13 13:43:46 +00:00
if ( listener - > linger_timeout ! = ( time_t ) - 1 ) {
2014-01-22 21:28:53 +00:00
switch_snprintf ( reply , reply_len , " +OK will linger %d seconds " , ( int ) linger_time ) ;
2012-04-13 13:43:46 +00:00
} else {
switch_snprintf ( reply , reply_len , " +OK will linger " ) ;
}
2009-01-16 15:32:10 +00:00
} else {
switch_snprintf ( reply , reply_len , " -ERR not controlling a session " ) ;
}
2009-07-15 16:45:12 +00:00
} else if ( ! strncasecmp ( cmd , " nolinger " , 8 ) ) {
2009-01-16 15:32:10 +00:00
if ( listener - > session ) {
switch_clear_flag_locked ( listener , LFLAG_LINGER ) ;
switch_snprintf ( reply , reply_len , " +OK will not linger " ) ;
} else {
switch_snprintf ( reply , reply_len , " -ERR not controlling a session " ) ;
}
2006-07-22 21:49:52 +00:00
} else if ( ! strncasecmp ( cmd , " nolog " , 5 ) ) {
2008-10-29 19:15:14 +00:00
flush_listener ( listener , SWITCH_TRUE , SWITCH_FALSE ) ;
2006-07-22 21:49:52 +00:00
if ( switch_test_flag ( listener , LFLAG_LOG ) ) {
switch_clear_flag_locked ( listener , LFLAG_LOG ) ;
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " +OK no longer logging " ) ;
2006-07-22 21:49:52 +00:00
} else {
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " -ERR not loging " ) ;
2006-07-22 21:49:52 +00:00
}
} else if ( ! strncasecmp ( cmd , " event " , 5 ) ) {
char * next , * cur ;
uint32_t count = 0 , key_count = 0 ;
uint8_t custom = 0 ;
2007-03-29 22:31:56 +00:00
2006-07-22 21:49:52 +00:00
strip_cr ( cmd ) ;
cur = cmd + 5 ;
2019-07-12 15:58:32 +00:00
if ( ( cur = strchr ( cur , ' ' ) ) ) {
2007-03-29 22:31:56 +00:00
for ( cur + + ; cur ; count + + ) {
2006-07-22 21:49:52 +00:00
switch_event_types_t type ;
if ( ( next = strchr ( cur , ' ' ) ) ) {
* next + + = ' \0 ' ;
}
2007-03-29 22:31:56 +00:00
2006-07-22 21:49:52 +00:00
if ( ! count ) {
if ( ! strcasecmp ( cur , " xml " ) ) {
listener - > format = EVENT_FORMAT_XML ;
goto end ;
} else if ( ! strcasecmp ( cur , " plain " ) ) {
listener - > format = EVENT_FORMAT_PLAIN ;
goto end ;
2010-06-17 16:43:09 +00:00
} else if ( ! strcasecmp ( cur , " json " ) ) {
listener - > format = EVENT_FORMAT_JSON ;
goto end ;
2006-07-22 21:49:52 +00:00
}
}
2010-02-06 03:38:24 +00:00
2006-07-22 21:49:52 +00:00
if ( custom ) {
2010-01-06 16:59:53 +00:00
if ( ! listener - > allowed_event_hash | | switch_core_hash_find ( listener - > allowed_event_hash , cur ) ) {
2010-01-05 19:47:49 +00:00
switch_core_hash_insert ( listener - > event_hash , cur , MARKER ) ;
} else {
switch_snprintf ( reply , reply_len , " -ERR permission denied " ) ;
goto done ;
}
2006-07-22 21:49:52 +00:00
} else if ( switch_name_event ( cur , & type ) = = SWITCH_STATUS_SUCCESS ) {
2010-02-06 03:38:24 +00:00
if ( switch_test_flag ( listener , LFLAG_AUTH_EVENTS ) & & ! listener - > allowed_event_list [ type ] & &
2010-01-05 19:47:49 +00:00
! switch_test_flag ( listener , LFLAG_ALL_EVENTS_AUTHED ) ) {
switch_snprintf ( reply , reply_len , " -ERR permission denied " ) ;
goto done ;
}
2006-07-22 21:49:52 +00:00
key_count + + ;
2006-09-20 14:57:13 +00:00
if ( type = = SWITCH_EVENT_ALL ) {
uint32_t x = 0 ;
for ( x = 0 ; x < SWITCH_EVENT_ALL ; x + + ) {
2007-07-24 21:26:04 +00:00
listener - > event_list [ x ] = 1 ;
2006-09-20 14:57:13 +00:00
}
2015-09-21 23:00:14 +00:00
if ( ! listener - > allowed_event_hash ) {
set_all_custom ( listener ) ;
} else {
set_allowed_custom ( listener ) ;
}
2006-09-20 14:57:13 +00:00
}
2007-12-16 03:01:50 +00:00
if ( type < = SWITCH_EVENT_ALL ) {
listener - > event_list [ type ] = 1 ;
}
2006-07-22 21:49:52 +00:00
if ( type = = SWITCH_EVENT_CUSTOM ) {
custom + + ;
}
}
2008-05-27 04:54:52 +00:00
end :
2006-07-22 21:49:52 +00:00
cur = next ;
}
2007-03-29 22:31:56 +00:00
}
2006-07-22 21:49:52 +00:00
if ( ! key_count ) {
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " -ERR no keywords supplied " ) ;
2006-07-22 21:49:52 +00:00
goto done ;
}
if ( ! switch_test_flag ( listener , LFLAG_EVENTS ) ) {
switch_set_flag_locked ( listener , LFLAG_EVENTS ) ;
}
2010-06-17 16:43:09 +00:00
switch_snprintf ( reply , reply_len , " +OK event listener enabled %s " , format2str ( listener - > format ) ) ;
2006-09-20 14:57:13 +00:00
} else if ( ! strncasecmp ( cmd , " nixevent " , 8 ) ) {
char * next , * cur ;
uint32_t count = 0 , key_count = 0 ;
uint8_t custom = 0 ;
2007-03-29 22:31:56 +00:00
2006-09-20 14:57:13 +00:00
strip_cr ( cmd ) ;
2015-09-21 23:00:14 +00:00
cur = cmd + 8 ;
2006-09-20 14:57:13 +00:00
2019-07-12 15:58:32 +00:00
if ( ( cur = strchr ( cur , ' ' ) ) ) {
2007-03-29 22:31:56 +00:00
for ( cur + + ; cur ; count + + ) {
2006-09-20 14:57:13 +00:00
switch_event_types_t type ;
if ( ( next = strchr ( cur , ' ' ) ) ) {
* next + + = ' \0 ' ;
}
2007-03-29 22:31:56 +00:00
2006-09-20 14:57:13 +00:00
if ( custom ) {
switch_core_hash_delete ( listener - > event_hash , cur ) ;
} else if ( switch_name_event ( cur , & type ) = = SWITCH_STATUS_SUCCESS ) {
uint32_t x = 0 ;
key_count + + ;
2007-07-24 21:26:04 +00:00
if ( type = = SWITCH_EVENT_CUSTOM ) {
custom + + ;
} else if ( type = = SWITCH_EVENT_ALL ) {
2006-09-20 14:57:13 +00:00
for ( x = 0 ; x < = SWITCH_EVENT_ALL ; x + + ) {
listener - > event_list [ x ] = 0 ;
}
} else {
if ( listener - > event_list [ SWITCH_EVENT_ALL ] ) {
listener - > event_list [ SWITCH_EVENT_ALL ] = 0 ;
for ( x = 0 ; x < SWITCH_EVENT_ALL ; x + + ) {
listener - > event_list [ x ] = 1 ;
}
}
listener - > event_list [ type ] = 0 ;
}
}
cur = next ;
}
2007-03-29 22:31:56 +00:00
}
2006-09-20 14:57:13 +00:00
if ( ! key_count ) {
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " -ERR no keywords supplied " ) ;
2006-09-20 14:57:13 +00:00
goto done ;
}
if ( ! switch_test_flag ( listener , LFLAG_EVENTS ) ) {
switch_set_flag_locked ( listener , LFLAG_EVENTS ) ;
}
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " +OK events nixed " ) ;
2007-03-29 22:31:56 +00:00
2006-07-22 21:49:52 +00:00
} else if ( ! strncasecmp ( cmd , " noevents " , 8 ) ) {
2008-10-29 19:15:14 +00:00
flush_listener ( listener , SWITCH_FALSE , SWITCH_TRUE ) ;
2006-08-11 18:59:25 +00:00
2006-07-22 21:49:52 +00:00
if ( switch_test_flag ( listener , LFLAG_EVENTS ) ) {
uint8_t x = 0 ;
switch_clear_flag_locked ( listener , LFLAG_EVENTS ) ;
for ( x = 0 ; x < = SWITCH_EVENT_ALL ; x + + ) {
listener - > event_list [ x ] = 0 ;
}
/* wipe the hash */
2007-09-29 01:06:08 +00:00
switch_core_hash_destroy ( & listener - > event_hash ) ;
2014-03-08 19:37:09 +00:00
switch_core_hash_init ( & listener - > event_hash ) ;
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " +OK no longer listening for events " ) ;
2006-07-22 21:49:52 +00:00
} else {
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " -ERR not listening for events " ) ;
2006-07-22 21:49:52 +00:00
}
2007-03-29 22:31:56 +00:00
}
2010-02-06 03:38:24 +00:00
done :
2006-07-25 14:14:07 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( reply ) ) {
2007-12-12 21:53:32 +00:00
switch_snprintf ( reply , reply_len , " -ERR command not found " ) ;
2006-07-22 21:49:52 +00:00
}
2010-02-06 03:38:24 +00:00
done_noreply :
2008-08-21 16:09:22 +00:00
if ( event ) {
switch_event_destroy ( event ) ;
}
2006-07-25 14:14:07 +00:00
return status ;
2006-07-22 21:49:52 +00:00
}
2008-05-27 04:54:52 +00:00
static void * SWITCH_THREAD_FUNC listener_run ( switch_thread_t * thread , void * obj )
2006-07-22 21:49:52 +00:00
{
listener_t * listener = ( listener_t * ) obj ;
char buf [ 1024 ] ;
switch_size_t len ;
switch_status_t status ;
2006-07-25 14:14:07 +00:00
switch_event_t * event ;
2006-07-22 21:49:52 +00:00
char reply [ 512 ] = " " ;
2007-03-29 22:31:56 +00:00
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
2008-08-20 19:10:04 +00:00
switch_event_t * revent = NULL ;
2009-04-30 22:45:46 +00:00
const char * var ;
2012-01-05 14:49:56 +00:00
int locked = 1 ;
2008-03-26 22:14:09 +00:00
2008-11-07 14:48:49 +00:00
switch_mutex_lock ( globals . listener_mutex ) ;
2007-07-24 21:26:04 +00:00
prefs . threads + + ;
2008-11-07 14:48:49 +00:00
switch_mutex_unlock ( globals . listener_mutex ) ;
2010-02-06 03:38:24 +00:00
2007-12-16 03:01:50 +00:00
switch_assert ( listener ! = NULL ) ;
2010-02-06 03:38:24 +00:00
2019-11-13 13:56:57 +00:00
if ( ( session = listener - > session ) ) {
if ( switch_core_session_read_lock ( session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Unable to lock session! \n " ) ;
locked = 0 ;
goto done ;
}
2019-11-11 18:58:18 +00:00
}
if ( ! listener - > sock ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Listener socket is null! \n " ) ;
switch_clear_flag_locked ( listener , LFLAG_RUNNING ) ;
goto done ;
2008-11-11 13:32:11 +00:00
}
2006-07-22 21:49:52 +00:00
2009-01-15 22:11:27 +00:00
switch_socket_opt_set ( listener - > sock , SWITCH_SO_TCP_NODELAY , TRUE ) ;
switch_socket_opt_set ( listener - > sock , SWITCH_SO_NONBLOCK , TRUE ) ;
2009-10-23 16:03:42 +00:00
if ( prefs . acl_count & & listener - > sa & & ! zstr ( listener - > remote_ip ) ) {
2008-03-31 16:05:32 +00:00
uint32_t x = 0 ;
2008-05-27 04:54:52 +00:00
for ( x = 0 ; x < prefs . acl_count ; x + + ) {
2008-03-26 22:14:09 +00:00
if ( ! switch_check_network_list_ip ( listener - > remote_ip , prefs . acl [ x ] ) ) {
const char message [ ] = " Access Denied, go away. \n " ;
2014-01-22 21:28:53 +00:00
int mlen = ( int ) strlen ( message ) ;
2008-03-26 22:14:09 +00:00
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " IP %s Rejected by acl \" %s \" \n " , listener - > remote_ip ,
prefs . acl [ x ] ) ;
2008-03-26 22:14:09 +00:00
2008-12-11 15:25:59 +00:00
switch_snprintf ( buf , sizeof ( buf ) , " Content-Type: text/rude-rejection \n Content-Length: %d \n \n " , mlen ) ;
2008-03-26 22:14:09 +00:00
len = strlen ( buf ) ;
switch_socket_send ( listener - > sock , buf , & len ) ;
len = mlen ;
switch_socket_send ( listener - > sock , message , & len ) ;
goto done ;
}
}
}
2010-02-06 03:38:24 +00:00
2009-05-02 00:58:51 +00:00
if ( globals . debug > 0 ) {
2009-10-23 16:03:42 +00:00
if ( zstr ( listener - > remote_ip ) ) {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Connection Open \n " ) ;
2009-05-02 00:58:51 +00:00
} else {
2010-02-06 03:38:24 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Connection Open from %s:%d \n " , listener - > remote_ip ,
listener - > remote_port ) ;
2009-05-02 00:58:51 +00:00
}
2008-03-26 22:14:09 +00:00
}
2006-07-22 21:49:52 +00:00
2007-03-09 20:44:13 +00:00
switch_socket_opt_set ( listener - > sock , SWITCH_SO_NONBLOCK , TRUE ) ;
2006-07-22 21:49:52 +00:00
switch_set_flag_locked ( listener , LFLAG_RUNNING ) ;
add_listener ( listener ) ;
2007-03-29 22:31:56 +00:00
if ( session & & switch_test_flag ( listener , LFLAG_AUTHED ) ) {
2009-03-23 19:53:57 +00:00
switch_event_t * ievent = NULL ;
2010-02-06 03:38:24 +00:00
2007-03-29 22:31:56 +00:00
switch_set_flag_locked ( listener , LFLAG_SESSION ) ;
2007-12-16 03:01:50 +00:00
status = read_packet ( listener , & ievent , 25 ) ;
2007-03-29 22:31:56 +00:00
2007-12-16 03:01:50 +00:00
if ( status ! = SWITCH_STATUS_SUCCESS | | ! ievent ) {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_CRIT , " Socket Error! \n " ) ;
2007-03-29 22:31:56 +00:00
switch_clear_flag_locked ( listener , LFLAG_RUNNING ) ;
goto done ;
}
2010-02-06 03:38:24 +00:00
2007-03-29 22:31:56 +00:00
2008-08-21 16:09:22 +00:00
if ( parse_command ( listener , & ievent , reply , sizeof ( reply ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:31:56 +00:00
switch_clear_flag_locked ( listener , LFLAG_RUNNING ) ;
goto done ;
}
} else {
2007-12-12 21:53:32 +00:00
switch_snprintf ( buf , sizeof ( buf ) , " Content-Type: auth/request \n \n " ) ;
2007-03-29 22:31:56 +00:00
len = strlen ( buf ) ;
switch_socket_send ( listener - > sock , buf , & len ) ;
while ( ! switch_test_flag ( listener , LFLAG_AUTHED ) ) {
status = read_packet ( listener , & event , 25 ) ;
if ( status ! = SWITCH_STATUS_SUCCESS ) {
goto done ;
}
if ( ! event ) {
continue ;
}
2008-08-21 16:09:22 +00:00
if ( parse_command ( listener , & event , reply , sizeof ( reply ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:31:56 +00:00
switch_clear_flag_locked ( listener , LFLAG_RUNNING ) ;
goto done ;
}
2007-08-03 21:29:01 +00:00
if ( * reply ! = ' \0 ' ) {
2008-06-06 16:14:29 +00:00
if ( * reply = = ' ~ ' ) {
switch_snprintf ( buf , sizeof ( buf ) , " Content-Type: command/reply \n %s " , reply + 1 ) ;
} else {
switch_snprintf ( buf , sizeof ( buf ) , " Content-Type: command/reply \n Reply-Text: %s \n \n " , reply ) ;
}
2007-03-29 22:31:56 +00:00
len = strlen ( buf ) ;
switch_socket_send ( listener - > sock , buf , & len ) ;
}
break ;
}
}
2009-02-20 01:10:59 +00:00
while ( ! prefs . done & & switch_test_flag ( listener , LFLAG_RUNNING ) & & listen_list . ready ) {
2006-07-22 21:49:52 +00:00
len = sizeof ( buf ) ;
memset ( buf , 0 , len ) ;
2007-12-16 03:01:50 +00:00
status = read_packet ( listener , & revent , 0 ) ;
2007-03-29 22:31:56 +00:00
2006-07-25 14:14:07 +00:00
if ( status ! = SWITCH_STATUS_SUCCESS ) {
2006-07-22 21:49:52 +00:00
break ;
}
2006-07-25 14:14:07 +00:00
2007-12-16 03:01:50 +00:00
if ( ! revent ) {
2006-07-22 21:49:52 +00:00
continue ;
}
2008-08-21 16:09:22 +00:00
if ( parse_command ( listener , & revent , reply , sizeof ( reply ) ) ! = SWITCH_STATUS_SUCCESS ) {
2006-07-25 14:14:07 +00:00
switch_clear_flag_locked ( listener , LFLAG_RUNNING ) ;
break ;
2006-07-22 21:49:52 +00:00
}
2008-08-21 17:32:57 +00:00
if ( revent ) {
switch_event_destroy ( & revent ) ;
}
2008-08-20 19:10:04 +00:00
2007-08-03 21:29:01 +00:00
if ( * reply ! = ' \0 ' ) {
2008-06-06 16:14:29 +00:00
if ( * reply = = ' ~ ' ) {
switch_snprintf ( buf , sizeof ( buf ) , " Content-Type: command/reply \n %s " , reply + 1 ) ;
} else {
switch_snprintf ( buf , sizeof ( buf ) , " Content-Type: command/reply \n Reply-Text: %s \n \n " , reply ) ;
}
2006-10-13 14:32:38 +00:00
len = strlen ( buf ) ;
2006-07-25 14:14:07 +00:00
switch_socket_send ( listener - > sock , buf , & len ) ;
2006-07-22 21:49:52 +00:00
}
2007-03-29 22:31:56 +00:00
2006-07-22 21:49:52 +00:00
}
2008-05-27 04:54:52 +00:00
done :
2010-02-06 03:38:24 +00:00
2008-08-21 17:32:57 +00:00
if ( revent ) {
switch_event_destroy ( & revent ) ;
}
2010-02-06 03:38:24 +00:00
2006-07-22 21:49:52 +00:00
remove_listener ( listener ) ;
2009-05-02 00:58:51 +00:00
if ( globals . debug > 0 ) {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Session complete, waiting for children \n " ) ;
2009-05-02 00:58:51 +00:00
}
2006-09-07 03:58:01 +00:00
switch_thread_rwlock_wrlock ( listener - > rwlock ) ;
2008-10-29 19:15:14 +00:00
flush_listener ( listener , SWITCH_TRUE , SWITCH_TRUE ) ;
2008-10-30 00:39:55 +00:00
switch_mutex_lock ( listener - > filter_mutex ) ;
if ( listener - > filters ) {
switch_event_destroy ( & listener - > filters ) ;
}
switch_mutex_unlock ( listener - > filter_mutex ) ;
2009-04-30 22:45:46 +00:00
2009-12-21 22:48:33 +00:00
if ( listener - > session ) {
2009-04-30 22:45:46 +00:00
channel = switch_core_session_get_channel ( listener - > session ) ;
2009-12-21 22:48:33 +00:00
}
2010-02-06 03:38:24 +00:00
2016-05-18 17:47:30 +00:00
if ( channel & & switch_channel_get_state ( channel ) ! = CS_HIBERNATE & &
2016-05-16 17:23:11 +00:00
! switch_channel_test_flag ( channel , CF_REDIRECT ) & & ! switch_channel_test_flag ( channel , CF_TRANSFER ) & & ! switch_channel_test_flag ( channel , CF_RESET ) & &
( switch_test_flag ( listener , LFLAG_RESUME ) | | ( ( var = switch_channel_get_variable ( channel , " socket_resume " ) ) & & switch_true ( var ) ) ) ) {
2009-04-30 22:45:46 +00:00
switch_channel_set_state ( channel , CS_RESET ) ;
}
2009-12-21 22:48:33 +00:00
2008-10-20 16:33:46 +00:00
if ( listener - > sock ) {
2011-01-25 20:13:15 +00:00
send_disconnect ( listener , " Disconnected, goodbye. \n See you at ClueCon! http://www.cluecon.com/ \n " ) ;
2008-10-20 16:33:46 +00:00
close_socket ( & listener - > sock ) ;
}
2006-09-07 03:58:01 +00:00
switch_thread_rwlock_unlock ( listener - > rwlock ) ;
2007-03-29 22:31:56 +00:00
2009-05-02 00:58:51 +00:00
if ( globals . debug > 0 ) {
2009-08-13 21:52:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Connection Closed \n " ) ;
2009-05-02 00:58:51 +00:00
}
2007-09-29 01:06:08 +00:00
switch_core_hash_destroy ( & listener - > event_hash ) ;
2006-07-22 21:49:52 +00:00
2010-01-05 19:47:49 +00:00
if ( listener - > allowed_event_hash ) {
switch_core_hash_destroy ( & listener - > allowed_event_hash ) ;
}
if ( listener - > allowed_api_hash ) {
switch_core_hash_destroy ( & listener - > allowed_api_hash ) ;
}
2008-10-22 16:32:55 +00:00
if ( listener - > session ) {
switch_channel_clear_flag ( switch_core_session_get_channel ( listener - > session ) , CF_CONTROLLED ) ;
2007-03-29 22:31:56 +00:00
switch_clear_flag_locked ( listener , LFLAG_SESSION ) ;
2012-01-05 14:49:56 +00:00
if ( locked ) {
switch_core_session_rwunlock ( listener - > session ) ;
}
2007-03-29 22:31:56 +00:00
} else if ( listener - > pool ) {
2006-07-22 21:49:52 +00:00
switch_memory_pool_t * pool = listener - > pool ;
switch_core_destroy_memory_pool ( & pool ) ;
}
2008-11-07 14:48:49 +00:00
switch_mutex_lock ( globals . listener_mutex ) ;
2007-07-24 21:26:04 +00:00
prefs . threads - - ;
2008-11-07 14:48:49 +00:00
switch_mutex_unlock ( globals . listener_mutex ) ;
2007-03-29 22:31:56 +00:00
2006-07-22 21:49:52 +00:00
return NULL ;
}
2006-08-29 20:27:43 +00:00
/* Create a thread for the socket and launch it */
2008-05-27 04:54:52 +00:00
static void launch_listener_thread ( listener_t * listener )
2006-07-22 21:49:52 +00:00
{
switch_thread_t * thread ;
switch_threadattr_t * thd_attr = NULL ;
2007-03-29 22:31:56 +00:00
2006-07-22 21:49:52 +00:00
switch_threadattr_create ( & thd_attr , listener - > pool ) ;
switch_threadattr_detach_set ( thd_attr , 1 ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
switch_thread_create ( & thread , thd_attr , listener_run , listener , listener - > pool ) ;
}
static int config ( void )
{
char * cf = " event_socket.conf " ;
switch_xml_t cfg , xml , settings , param ;
memset ( & prefs , 0 , sizeof ( prefs ) ) ;
if ( ! ( xml = switch_xml_open_cfg ( cf , & cfg , NULL ) ) ) {
2008-10-11 06:19:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Open of %s failed \n " , cf ) ;
2006-07-22 21:49:52 +00:00
} else {
if ( ( settings = switch_xml_child ( cfg , " settings " ) ) ) {
for ( param = switch_xml_child ( settings , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcmp ( var , " listen-ip " ) ) {
set_pref_ip ( val ) ;
2009-05-02 00:58:51 +00:00
} else if ( ! strcmp ( var , " debug " ) ) {
globals . debug = atoi ( val ) ;
2009-06-03 14:25:35 +00:00
} else if ( ! strcmp ( var , " nat-map " ) ) {
2011-02-02 21:43:26 +00:00
if ( switch_true ( val ) & & switch_nat_get_type ( ) ) {
2009-06-03 14:25:35 +00:00
prefs . nat_map = 1 ;
}
2006-07-22 21:49:52 +00:00
} else if ( ! strcmp ( var , " listen-port " ) ) {
2007-03-29 22:31:56 +00:00
prefs . port = ( uint16_t ) atoi ( val ) ;
2006-07-22 21:49:52 +00:00
} else if ( ! strcmp ( var , " password " ) ) {
set_pref_pass ( val ) ;
2011-07-05 16:57:13 +00:00
} else if ( ! strcasecmp ( var , " apply-inbound-acl " ) & & ! zstr ( val ) ) {
2008-03-26 22:14:09 +00:00
if ( prefs . acl_count < MAX_ACL ) {
prefs . acl [ prefs . acl_count + + ] = strdup ( val ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Max acl records of %d reached \n " , MAX_ACL ) ;
}
2014-02-24 10:28:25 +00:00
} else if ( ! strcasecmp ( var , " stop-on-bind-error " ) ) {
prefs . stop_on_bind_error = switch_true ( val ) ? 1 : 0 ;
2007-03-29 22:31:56 +00:00
}
2006-07-22 21:49:52 +00:00
}
}
switch_xml_free ( xml ) ;
}
2007-03-29 22:31:56 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( prefs . ip ) ) {
2006-07-22 21:49:52 +00:00
set_pref_ip ( " 127.0.0.1 " ) ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( prefs . password ) ) {
2006-07-22 21:49:52 +00:00
set_pref_pass ( " ClueCon " ) ;
}
2009-06-03 14:25:35 +00:00
if ( ! prefs . nat_map ) {
prefs . nat_map = 0 ;
}
2015-06-11 13:24:31 +00:00
if ( ! prefs . acl_count ) {
prefs . acl [ prefs . acl_count + + ] = strdup ( " loopback.auto " ) ;
}
2009-06-08 23:28:51 +00:00
if ( prefs . nat_map ) {
2009-06-03 19:42:53 +00:00
prefs . nat_map = 0 ;
}
2006-07-22 21:49:52 +00:00
if ( ! prefs . port ) {
prefs . port = 8021 ;
}
return 0 ;
}
2007-06-13 17:06:10 +00:00
SWITCH_MODULE_RUNTIME_FUNCTION ( mod_event_socket_runtime )
2006-07-22 21:49:52 +00:00
{
switch_memory_pool_t * pool = NULL , * listener_pool = NULL ;
2007-03-29 22:31:56 +00:00
switch_status_t rv ;
switch_sockaddr_t * sa ;
switch_socket_t * inbound_socket = NULL ;
2006-07-22 21:49:52 +00:00
listener_t * listener ;
2008-03-31 16:05:32 +00:00
uint32_t x = 0 ;
2009-11-25 19:59:26 +00:00
uint32_t errs = 0 ;
2006-07-22 21:49:52 +00:00
if ( switch_core_new_memory_pool ( & pool ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " OH OH no pool \n " ) ;
return SWITCH_STATUS_TERM ;
}
2008-12-31 19:07:20 +00:00
config ( ) ;
2007-03-29 22:31:56 +00:00
2010-02-06 03:38:24 +00:00
while ( ! prefs . done ) {
2012-03-14 15:05:03 +00:00
rv = switch_sockaddr_info_get ( & sa , prefs . ip , SWITCH_UNSPEC , prefs . port , 0 , pool ) ;
2019-07-08 11:19:03 +00:00
if ( rv ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot get information about IP address %s \n " , prefs . ip ) ;
2007-03-29 22:31:56 +00:00
goto fail ;
2019-07-08 11:19:03 +00:00
}
2007-03-30 00:13:31 +00:00
rv = switch_socket_create ( & listen_list . sock , switch_sockaddr_get_family ( sa ) , SOCK_STREAM , SWITCH_PROTO_TCP , pool ) ;
2007-03-29 22:31:56 +00:00
if ( rv )
goto sock_fail ;
2006-09-07 03:58:01 +00:00
rv = switch_socket_opt_set ( listen_list . sock , SWITCH_SO_REUSEADDR , 1 ) ;
2007-03-29 22:31:56 +00:00
if ( rv )
goto sock_fail ;
2013-01-11 17:12:50 +00:00
# ifdef WIN32
/* Enable dual-stack listening on Windows (if the listening address is IPv6), it's default on Linux */
if ( switch_sockaddr_get_family ( sa ) = = AF_INET6 ) {
rv = switch_socket_opt_set ( listen_list . sock , 16384 , 0 ) ;
if ( rv ) goto sock_fail ;
}
# endif
2006-07-22 21:49:52 +00:00
rv = switch_socket_bind ( listen_list . sock , sa ) ;
2007-03-29 22:31:56 +00:00
if ( rv )
goto sock_fail ;
2006-07-22 21:49:52 +00:00
rv = switch_socket_listen ( listen_list . sock , 5 ) ;
2007-03-29 22:31:56 +00:00
if ( rv )
goto sock_fail ;
2006-07-22 21:49:52 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Socket up listening on %s:%u \n " , prefs . ip , prefs . port ) ;
2009-06-03 14:25:35 +00:00
if ( prefs . nat_map ) {
2009-06-30 18:59:05 +00:00
switch_nat_add_mapping ( prefs . port , SWITCH_NAT_TCP , NULL , SWITCH_FALSE ) ;
2009-06-03 14:25:35 +00:00
}
2006-07-22 21:49:52 +00:00
break ;
2008-05-27 04:54:52 +00:00
sock_fail :
2008-04-21 15:25:09 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Socket Error! Could not listen on %s:%u \n " , prefs . ip , prefs . port ) ;
2014-02-24 10:28:25 +00:00
if ( prefs . stop_on_bind_error ) {
prefs . done = 1 ;
goto fail ;
}
2006-09-07 03:58:01 +00:00
switch_yield ( 100000 ) ;
2006-07-22 21:49:52 +00:00
}
listen_list . ready = 1 ;
2010-02-06 03:38:24 +00:00
while ( ! prefs . done ) {
2006-07-22 21:49:52 +00:00
if ( switch_core_new_memory_pool ( & listener_pool ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " OH OH no pool \n " ) ;
goto fail ;
}
2007-03-29 22:31:56 +00:00
2010-02-06 03:38:24 +00:00
2006-07-22 21:49:52 +00:00
if ( ( rv = switch_socket_accept ( & inbound_socket , listen_list . sock , listener_pool ) ) ) {
2006-11-09 05:39:04 +00:00
if ( prefs . done ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Shutting Down \n " ) ;
2009-11-25 19:59:26 +00:00
goto end ;
2006-11-09 05:39:04 +00:00
} else {
2009-11-25 19:59:26 +00:00
/* I wish we could use strerror_r here but its not defined everywhere =/ */
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Socket Error [%s] \n " , strerror ( errno ) ) ;
if ( + + errs > 100 ) {
goto end ;
}
2006-11-09 05:39:04 +00:00
}
2009-11-25 19:59:26 +00:00
} else {
errs = 0 ;
2006-07-22 21:49:52 +00:00
}
2007-03-29 22:31:56 +00:00
2010-02-06 03:38:24 +00:00
2006-07-22 21:49:52 +00:00
if ( ! ( listener = switch_core_alloc ( listener_pool , sizeof ( * listener ) ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Memory Error \n " ) ;
break ;
}
2007-03-29 22:31:56 +00:00
2006-09-07 03:58:01 +00:00
switch_thread_rwlock_create ( & listener - > rwlock , listener_pool ) ;
2010-07-24 06:03:21 +00:00
switch_queue_create ( & listener - > event_queue , MAX_QUEUE_LEN , listener_pool ) ;
switch_queue_create ( & listener - > log_queue , MAX_QUEUE_LEN , listener_pool ) ;
2006-07-22 21:49:52 +00:00
listener - > sock = inbound_socket ;
listener - > pool = listener_pool ;
2006-08-29 20:27:43 +00:00
listener_pool = NULL ;
2006-07-22 21:49:52 +00:00
listener - > format = EVENT_FORMAT_PLAIN ;
2008-12-12 15:44:37 +00:00
switch_set_flag ( listener , LFLAG_FULL ) ;
2010-01-05 19:47:49 +00:00
switch_set_flag ( listener , LFLAG_ALLOW_LOG ) ;
2006-08-29 20:27:43 +00:00
switch_mutex_init ( & listener - > flag_mutex , SWITCH_MUTEX_NESTED , listener - > pool ) ;
2008-10-30 00:39:55 +00:00
switch_mutex_init ( & listener - > filter_mutex , SWITCH_MUTEX_NESTED , listener - > pool ) ;
2014-03-08 19:37:09 +00:00
switch_core_hash_init ( & listener - > event_hash ) ;
2012-06-26 14:58:51 +00:00
switch_socket_create_pollset ( & listener - > pollfd , listener - > sock , SWITCH_POLLIN | SWITCH_POLLERR , listener - > pool ) ;
2007-03-29 22:31:56 +00:00
2010-05-13 15:03:49 +00:00
if ( switch_socket_addr_get ( & listener - > sa , SWITCH_TRUE , listener - > sock ) = = SWITCH_STATUS_SUCCESS & & listener - > sa ) {
switch_get_addr ( listener - > remote_ip , sizeof ( listener - > remote_ip ) , listener - > sa ) ;
2019-07-12 15:58:32 +00:00
if ( ( listener - > remote_port = switch_sockaddr_get_port ( listener - > sa ) ) ) {
2010-05-13 15:03:49 +00:00
launch_listener_thread ( listener ) ;
continue ;
2017-01-06 07:10:15 +00:00
}
2010-05-13 15:03:49 +00:00
}
2017-01-06 07:10:15 +00:00
2010-05-13 15:03:49 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error initilizing connection \n " ) ;
close_socket ( & listener - > sock ) ;
expire_listener ( & listener ) ;
2017-01-06 07:10:15 +00:00
2006-07-22 21:49:52 +00:00
}
2010-02-06 03:38:24 +00:00
end :
2009-11-25 19:59:26 +00:00
2006-07-22 21:49:52 +00:00
close_socket ( & listen_list . sock ) ;
2010-02-06 03:38:24 +00:00
2011-02-02 21:43:26 +00:00
if ( prefs . nat_map & & switch_nat_get_type ( ) ) {
2009-06-03 14:25:35 +00:00
switch_nat_del_mapping ( prefs . port , SWITCH_NAT_TCP ) ;
}
2006-07-22 21:49:52 +00:00
if ( pool ) {
switch_core_destroy_memory_pool ( & pool ) ;
}
if ( listener_pool ) {
switch_core_destroy_memory_pool ( & listener_pool ) ;
}
2008-03-26 22:14:09 +00:00
2008-05-27 04:54:52 +00:00
for ( x = 0 ; x < prefs . acl_count ; x + + ) {
2008-03-26 22:14:09 +00:00
switch_safe_free ( prefs . acl [ x ] ) ;
}
2008-05-27 04:54:52 +00:00
fail :
2006-07-22 21:49:52 +00:00
return SWITCH_STATUS_TERM ;
}
2006-11-27 22:30:48 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2008-02-03 22:14:57 +00:00
* indent - tabs - mode : t
2006-11-27 22:30:48 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2013-06-25 16:50:17 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 noet :
2006-11-27 22:30:48 +00:00
*/