2005-12-13 20:52:33 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2012-04-18 11:51:48 -05:00
* Copyright ( C ) 2005 - 2012 , Anthony Minessale II < anthm @ freeswitch . org >
2005-12-13 20:52:33 +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 >
2005-12-13 20:52:33 +00:00
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2006-09-18 05:08:55 +00:00
* Michael Jerris < mike @ jerris . com >
* Paul D . Tinsley < pdt at jackhammer . org >
2005-12-13 20:52:33 +00:00
*
*
* switch_event . c - - Event System
*
*/
2008-01-27 17:36:53 +00:00
2006-04-29 01:00:52 +00:00
# include <switch.h>
2006-04-29 06:05:03 +00:00
# include <switch_event.h>
2011-07-11 17:41:14 -05:00
//#define SWITCH_EVENT_RECYCLE
2011-04-29 10:29:03 -05:00
# define DISPATCH_QUEUE_LEN 10000
2008-03-14 16:21:13 +00:00
//#define DEBUG_DISPATCH_QUEUES
2005-12-13 20:52:33 +00:00
2008-07-01 23:41:09 +00:00
/*! \brief A node to store binded events */
struct switch_event_node {
/*! the id of the node */
char * id ;
/*! the event id enumeration to bind to */
switch_event_types_t event_id ;
/*! the event subclass to bind to for custom events */
2011-08-10 07:55:17 -05:00
char * subclass_name ;
2008-07-01 23:41:09 +00:00
/*! a callback function to execute when the event is triggered */
switch_event_callback_t callback ;
/*! private data */
void * user_data ;
struct switch_event_node * next ;
} ;
/*! \brief A registered custom event subclass */
struct switch_event_subclass {
/*! the owner of the subclass */
char * owner ;
/*! the subclass name */
char * name ;
2009-12-04 20:28:55 +00:00
/*! the subclass was reserved by a listener so it's ok for a module to reserve it still */
int bind ;
2008-07-01 23:41:09 +00:00
} ;
2012-05-03 16:31:21 -05:00
# define MAX_DISPATCH_VAL 64
2008-09-12 18:04:58 +00:00
static unsigned int MAX_DISPATCH = MAX_DISPATCH_VAL ;
static unsigned int SOFT_MAX_DISPATCH = 0 ;
2007-11-30 21:57:49 +00:00
static char guess_ip_v4 [ 80 ] = " " ;
static char guess_ip_v6 [ 80 ] = " " ;
2006-04-29 06:05:03 +00:00
static switch_event_node_t * EVENT_NODES [ SWITCH_EVENT_ALL + 1 ] = { NULL } ;
2008-07-01 23:41:09 +00:00
static switch_thread_rwlock_t * RWLOCK = NULL ;
2005-12-14 21:29:46 +00:00
static switch_mutex_t * BLOCK = NULL ;
2005-12-22 18:53:33 +00:00
static switch_mutex_t * POOL_LOCK = NULL ;
2006-04-29 01:00:52 +00:00
static switch_memory_pool_t * RUNTIME_POOL = NULL ;
static switch_memory_pool_t * THRUNTIME_POOL = NULL ;
2008-03-17 16:25:53 +00:00
# define NUMBER_OF_QUEUES 3
2009-02-20 01:10:59 +00:00
static switch_thread_t * EVENT_QUEUE_THREADS [ NUMBER_OF_QUEUES ] = { 0 } ;
2008-03-17 16:25:53 +00:00
static switch_queue_t * EVENT_QUEUE [ NUMBER_OF_QUEUES ] = { 0 } ;
2009-02-20 01:10:59 +00:00
static switch_thread_t * EVENT_DISPATCH_QUEUE_THREADS [ MAX_DISPATCH_VAL ] = { 0 } ;
2010-09-02 12:30:26 -05:00
static uint8_t EVENT_DISPATCH_QUEUE_RUNNING [ MAX_DISPATCH_VAL ] = { 0 } ;
2008-09-12 18:04:58 +00:00
static switch_queue_t * EVENT_DISPATCH_QUEUE [ MAX_DISPATCH_VAL ] = { 0 } ;
2006-06-05 17:37:24 +00:00
static int POOL_COUNT_MAX = SWITCH_CORE_QUEUE_LEN ;
2008-03-14 16:21:13 +00:00
static switch_mutex_t * EVENT_QUEUE_MUTEX = NULL ;
2006-04-29 01:00:52 +00:00
static switch_hash_t * CUSTOM_HASH = NULL ;
2008-03-14 16:21:13 +00:00
static int THREAD_COUNT = 0 ;
static int SYSTEM_RUNNING = 0 ;
2012-02-07 11:25:23 -06:00
static uint64_t EVENT_SEQUENCE_NR = 0 ;
2009-02-26 22:30:00 +00:00
# ifdef SWITCH_EVENT_RECYCLE
2007-09-30 20:05:18 +00:00
static switch_queue_t * EVENT_RECYCLE_QUEUE = NULL ;
static switch_queue_t * EVENT_HEADER_RECYCLE_QUEUE = NULL ;
2009-02-26 22:30:00 +00:00
# endif
2008-09-12 19:23:45 +00:00
static void launch_dispatch_threads ( uint32_t max , int len , switch_memory_pool_t * pool ) ;
2006-02-26 00:12:17 +00:00
2008-05-27 04:30:03 +00:00
static char * my_dup ( const char * s )
2007-09-29 01:06:08 +00:00
{
2008-05-27 04:30:03 +00:00
size_t len = strlen ( s ) + 1 ;
void * new = malloc ( len ) ;
2007-12-11 19:23:57 +00:00
switch_assert ( new ) ;
2007-09-29 01:06:08 +00:00
2008-05-27 04:30:03 +00:00
return ( char * ) memcpy ( new , s , len ) ;
2007-09-29 01:06:08 +00:00
}
2006-04-29 01:00:52 +00:00
# ifndef ALLOC
2006-03-29 19:11:20 +00:00
# define ALLOC(size) malloc(size)
2006-04-29 01:00:52 +00:00
# endif
# ifndef DUP
2007-09-29 01:06:08 +00:00
# define DUP(str) my_dup(str)
2006-04-29 01:00:52 +00:00
# endif
# ifndef FREE
2007-09-30 20:05:18 +00:00
# define FREE(ptr) switch_safe_free(ptr)
2006-04-29 01:00:52 +00:00
# endif
2005-12-22 18:53:33 +00:00
2006-04-29 01:00:52 +00:00
/* make sure this is synced with the switch_event_types_t enum in switch_types.h
2008-01-03 01:01:04 +00:00
also never put any new ones before EVENT_ALL
2005-12-13 20:52:33 +00:00
*/
static char * EVENT_NAMES [ ] = {
" CUSTOM " ,
2009-02-26 18:54:00 +00:00
" CLONE " ,
2006-04-04 21:26:21 +00:00
" CHANNEL_CREATE " ,
2006-04-25 23:11:56 +00:00
" CHANNEL_DESTROY " ,
2005-12-21 22:25:22 +00:00
" CHANNEL_STATE " ,
2010-06-07 18:01:02 -05:00
" CHANNEL_CALLSTATE " ,
2005-12-21 22:25:22 +00:00
" CHANNEL_ANSWER " ,
2006-01-05 21:03:22 +00:00
" CHANNEL_HANGUP " ,
2009-05-29 17:18:03 +00:00
" CHANNEL_HANGUP_COMPLETE " ,
2006-04-04 21:26:21 +00:00
" CHANNEL_EXECUTE " ,
2007-06-23 05:41:07 +00:00
" CHANNEL_EXECUTE_COMPLETE " ,
2010-06-08 16:22:21 -05:00
" CHANNEL_HOLD " ,
" CHANNEL_UNHOLD " ,
2006-04-11 14:55:14 +00:00
" CHANNEL_BRIDGE " ,
" CHANNEL_UNBRIDGE " ,
2006-08-29 15:17:06 +00:00
" CHANNEL_PROGRESS " ,
2008-10-02 15:38:45 +00:00
" CHANNEL_PROGRESS_MEDIA " ,
2006-08-29 15:17:06 +00:00
" CHANNEL_OUTGOING " ,
2006-09-07 03:58:01 +00:00
" CHANNEL_PARK " ,
" CHANNEL_UNPARK " ,
2007-06-23 05:41:07 +00:00
" CHANNEL_APPLICATION " ,
2007-10-16 13:56:44 +00:00
" CHANNEL_ORIGINATE " ,
2008-11-04 16:46:33 +00:00
" CHANNEL_UUID " ,
2005-12-23 02:24:56 +00:00
" API " ,
2005-12-21 22:25:22 +00:00
" LOG " ,
2005-12-13 20:52:33 +00:00
" INBOUND_CHAN " ,
" OUTBOUND_CHAN " ,
" STARTUP " ,
2005-12-14 21:29:46 +00:00
" SHUTDOWN " ,
2006-02-13 23:59:14 +00:00
" PUBLISH " ,
" UNPUBLISH " ,
2006-04-21 22:31:08 +00:00
" TALK " ,
" NOTALK " ,
2006-04-27 21:09:58 +00:00
" SESSION_CRASH " ,
2006-05-01 19:44:21 +00:00
" MODULE_LOAD " ,
2007-05-03 16:28:23 +00:00
" MODULE_UNLOAD " ,
2006-05-04 17:51:53 +00:00
" DTMF " ,
2006-07-25 14:14:07 +00:00
" MESSAGE " ,
2006-10-12 00:59:09 +00:00
" PRESENCE_IN " ,
2008-11-24 15:52:55 +00:00
" NOTIFY_IN " ,
2006-10-12 00:59:09 +00:00
" PRESENCE_OUT " ,
2006-12-16 03:00:56 +00:00
" PRESENCE_PROBE " ,
2007-04-02 20:20:46 +00:00
" MESSAGE_WAITING " ,
" MESSAGE_QUERY " ,
2006-10-18 22:57:35 +00:00
" ROSTER " ,
2006-08-25 01:33:28 +00:00
" CODEC " ,
2006-09-07 03:58:01 +00:00
" BACKGROUND_JOB " ,
2006-11-09 05:39:04 +00:00
" DETECTED_SPEECH " ,
2007-06-16 02:25:40 +00:00
" DETECTED_TONE " ,
2007-02-19 21:06:27 +00:00
" PRIVATE_COMMAND " ,
2007-02-22 17:38:34 +00:00
" HEARTBEAT " ,
2007-03-05 20:55:41 +00:00
" TRAP " ,
2007-03-30 00:10:33 +00:00
" ADD_SCHEDULE " ,
" DEL_SCHEDULE " ,
" EXE_SCHEDULE " ,
" RE_SCHEDULE " ,
2008-03-03 19:32:42 +00:00
" RELOADXML " ,
2008-07-22 22:23:50 +00:00
" NOTIFY " ,
" SEND_MESSAGE " ,
2008-07-23 18:19:56 +00:00
" RECV_MESSAGE " ,
2008-10-02 17:10:05 +00:00
" REQUEST_PARAMS " ,
" CHANNEL_DATA " ,
" GENERAL " ,
" COMMAND " ,
2008-10-07 21:03:37 +00:00
" SESSION_HEARTBEAT " ,
2009-02-21 23:19:58 +00:00
" CLIENT_DISCONNECTED " ,
" SERVER_DISCONNECTED " ,
2009-04-20 17:07:54 +00:00
" SEND_INFO " ,
" RECV_INFO " ,
2010-04-19 19:07:23 -05:00
" RECV_RTCP_MESSAGE " ,
2009-05-28 17:50:06 +00:00
" CALL_SECURE " ,
2009-06-30 18:59:05 +00:00
" NAT " ,
2009-08-21 22:29:44 +00:00
" RECORD_START " ,
" RECORD_STOP " ,
2011-02-25 10:55:33 -06:00
" PLAYBACK_START " ,
" PLAYBACK_STOP " ,
2009-10-09 15:59:22 +00:00
" CALL_UPDATE " ,
2009-12-09 14:42:30 +00:00
" FAILURE " ,
2010-01-04 17:46:55 +00:00
" SOCKET_DATA " ,
2010-03-02 01:11:15 +00:00
" MEDIA_BUG_START " ,
" MEDIA_BUG_STOP " ,
2005-12-13 20:52:33 +00:00
" ALL "
} ;
2006-04-29 06:05:03 +00:00
static int switch_events_match ( switch_event_t * event , switch_event_node_t * node )
2005-12-15 19:10:43 +00:00
{
int match = 0 ;
2010-02-06 03:38:24 +00:00
2005-12-19 18:55:31 +00:00
if ( node - > event_id = = SWITCH_EVENT_ALL ) {
2005-12-15 20:20:57 +00:00
match + + ;
2010-02-06 03:38:24 +00:00
2011-08-10 07:55:17 -05:00
if ( ! node - > subclass_name ) {
2005-12-15 20:20:57 +00:00
return match ;
}
2005-12-15 19:10:43 +00:00
}
2010-02-06 03:38:24 +00:00
2005-12-19 18:55:31 +00:00
if ( match | | event - > event_id = = node - > event_id ) {
2006-02-13 23:59:14 +00:00
2011-08-10 07:55:17 -05:00
if ( event - > subclass_name & & node - > subclass_name ) {
if ( ! strncasecmp ( node - > subclass_name , " file: " , 5 ) ) {
more event stuff
you should now be able to bind an event handler to a
paticiular file or function not just a paticular event
when using the custom event
like "file:somefile.c"
or "func:somefunc"
also events now have headers which can be added
with varargs and should be created and delivered with api calls
switch_event *event;
regular event:
if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "System Ready");
switch_event_fire(&event);
}
custom event:
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "some_subclass_string") == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "hello world %d", 42);
switch_event_fire(&event);
}
switch_event_add_header(event, "test %d", 42);
also you can serialize and event into a buffer in
a printable/transferrable format with optional body
char buf[1024];
with body:
switch_event_serialize(event, buf, sizeof(buf), "This is a body my favorite number is %d", 42);
no body:
switch_event_serialize(event, buf, sizeof(buf), NULL);
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@173 d0543943-73ff-0310-b7d9-9358b9ac24b2
2005-12-19 19:57:32 +00:00
char * file_header ;
2006-02-20 00:23:25 +00:00
if ( ( file_header = switch_event_get_header ( event , " file " ) ) ! = 0 ) {
2011-08-10 07:55:17 -05:00
match = strstr ( node - > subclass_name + 5 , file_header ) ? 1 : 0 ;
more event stuff
you should now be able to bind an event handler to a
paticiular file or function not just a paticular event
when using the custom event
like "file:somefile.c"
or "func:somefunc"
also events now have headers which can be added
with varargs and should be created and delivered with api calls
switch_event *event;
regular event:
if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "System Ready");
switch_event_fire(&event);
}
custom event:
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "some_subclass_string") == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "hello world %d", 42);
switch_event_fire(&event);
}
switch_event_add_header(event, "test %d", 42);
also you can serialize and event into a buffer in
a printable/transferrable format with optional body
char buf[1024];
with body:
switch_event_serialize(event, buf, sizeof(buf), "This is a body my favorite number is %d", 42);
no body:
switch_event_serialize(event, buf, sizeof(buf), NULL);
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@173 d0543943-73ff-0310-b7d9-9358b9ac24b2
2005-12-19 19:57:32 +00:00
}
2011-08-10 07:55:17 -05:00
} else if ( ! strncasecmp ( node - > subclass_name , " func: " , 5 ) ) {
more event stuff
you should now be able to bind an event handler to a
paticiular file or function not just a paticular event
when using the custom event
like "file:somefile.c"
or "func:somefunc"
also events now have headers which can be added
with varargs and should be created and delivered with api calls
switch_event *event;
regular event:
if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "System Ready");
switch_event_fire(&event);
}
custom event:
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "some_subclass_string") == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "hello world %d", 42);
switch_event_fire(&event);
}
switch_event_add_header(event, "test %d", 42);
also you can serialize and event into a buffer in
a printable/transferrable format with optional body
char buf[1024];
with body:
switch_event_serialize(event, buf, sizeof(buf), "This is a body my favorite number is %d", 42);
no body:
switch_event_serialize(event, buf, sizeof(buf), NULL);
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@173 d0543943-73ff-0310-b7d9-9358b9ac24b2
2005-12-19 19:57:32 +00:00
char * func_header ;
2006-02-20 00:23:25 +00:00
if ( ( func_header = switch_event_get_header ( event , " function " ) ) ! = 0 ) {
2011-08-10 07:55:17 -05:00
match = strstr ( node - > subclass_name + 5 , func_header ) ? 1 : 0 ;
more event stuff
you should now be able to bind an event handler to a
paticiular file or function not just a paticular event
when using the custom event
like "file:somefile.c"
or "func:somefunc"
also events now have headers which can be added
with varargs and should be created and delivered with api calls
switch_event *event;
regular event:
if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "System Ready");
switch_event_fire(&event);
}
custom event:
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "some_subclass_string") == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "hello world %d", 42);
switch_event_fire(&event);
}
switch_event_add_header(event, "test %d", 42);
also you can serialize and event into a buffer in
a printable/transferrable format with optional body
char buf[1024];
with body:
switch_event_serialize(event, buf, sizeof(buf), "This is a body my favorite number is %d", 42);
no body:
switch_event_serialize(event, buf, sizeof(buf), NULL);
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@173 d0543943-73ff-0310-b7d9-9358b9ac24b2
2005-12-19 19:57:32 +00:00
}
2011-08-10 07:55:17 -05:00
} else if ( event - > subclass_name & & node - > subclass_name ) {
match = strstr ( event - > subclass_name , node - > subclass_name ) ? 1 : 0 ;
more event stuff
you should now be able to bind an event handler to a
paticiular file or function not just a paticular event
when using the custom event
like "file:somefile.c"
or "func:somefunc"
also events now have headers which can be added
with varargs and should be created and delivered with api calls
switch_event *event;
regular event:
if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "System Ready");
switch_event_fire(&event);
}
custom event:
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "some_subclass_string") == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "hello world %d", 42);
switch_event_fire(&event);
}
switch_event_add_header(event, "test %d", 42);
also you can serialize and event into a buffer in
a printable/transferrable format with optional body
char buf[1024];
with body:
switch_event_serialize(event, buf, sizeof(buf), "This is a body my favorite number is %d", 42);
no body:
switch_event_serialize(event, buf, sizeof(buf), NULL);
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@173 d0543943-73ff-0310-b7d9-9358b9ac24b2
2005-12-19 19:57:32 +00:00
}
2011-08-10 07:55:17 -05:00
} else if ( ( event - > subclass_name & & ! node - > subclass_name ) | | ( ! event - > subclass_name & & ! node - > subclass_name ) ) {
2005-12-15 20:20:57 +00:00
match = 1 ;
} else {
2005-12-15 19:10:43 +00:00
match = 0 ;
}
}
return match ;
}
2008-05-27 04:30:03 +00:00
static void * SWITCH_THREAD_FUNC switch_event_dispatch_thread ( switch_thread_t * thread , void * obj )
2008-03-14 03:47:45 +00:00
{
switch_queue_t * queue = ( switch_queue_t * ) obj ;
2008-03-14 16:21:13 +00:00
int my_id = 0 ;
2010-09-02 12:30:26 -05:00
2008-03-14 16:21:13 +00:00
switch_mutex_lock ( EVENT_QUEUE_MUTEX ) ;
THREAD_COUNT + + ;
2008-03-17 16:25:53 +00:00
for ( my_id = 0 ; my_id < NUMBER_OF_QUEUES ; my_id + + ) {
2008-03-14 16:21:13 +00:00
if ( EVENT_DISPATCH_QUEUE [ my_id ] = = queue ) {
break ;
}
}
2010-09-02 12:30:26 -05:00
EVENT_DISPATCH_QUEUE_RUNNING [ my_id ] = 1 ;
switch_mutex_unlock ( EVENT_QUEUE_MUTEX ) ;
2012-05-03 16:31:21 -05:00
# ifdef HAVE_CPU_SET_MACROS
{
cpu_set_t set ;
CPU_ZERO ( & set ) ;
CPU_SET ( my_id , & set ) ;
sched_setaffinity ( 0 , sizeof ( set ) , & set ) ;
}
# endif
2008-05-27 04:30:03 +00:00
for ( ; ; ) {
2008-03-14 03:47:45 +00:00
void * pop = NULL ;
switch_event_t * event = NULL ;
2008-03-14 16:21:13 +00:00
2009-02-20 01:10:59 +00:00
if ( ! SYSTEM_RUNNING ) {
break ;
}
2008-03-14 03:47:45 +00:00
if ( switch_queue_pop ( queue , & pop ) ! = SWITCH_STATUS_SUCCESS ) {
break ;
}
if ( ! pop ) {
break ;
}
2008-05-27 04:30:03 +00:00
2008-03-14 03:47:45 +00:00
event = ( switch_event_t * ) pop ;
switch_event_deliver ( & event ) ;
}
2008-03-14 16:21:13 +00:00
switch_mutex_lock ( EVENT_QUEUE_MUTEX ) ;
2010-09-21 10:17:18 -05:00
EVENT_DISPATCH_QUEUE_RUNNING [ my_id ] = 0 ;
2008-03-14 16:21:13 +00:00
THREAD_COUNT - - ;
switch_mutex_unlock ( EVENT_QUEUE_MUTEX ) ;
2008-05-27 04:30:03 +00:00
2008-03-14 16:21:13 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Dispatch Thread %d Ended. \n " , my_id ) ;
2008-03-14 03:47:45 +00:00
return NULL ;
2008-05-27 04:30:03 +00:00
2008-03-14 03:47:45 +00:00
}
2008-03-14 16:21:13 +00:00
2008-05-27 04:30:03 +00:00
static void * SWITCH_THREAD_FUNC switch_event_thread ( switch_thread_t * thread , void * obj )
2005-12-14 20:22:19 +00:00
{
2008-03-14 16:21:13 +00:00
switch_queue_t * queue = ( switch_queue_t * ) obj ;
2008-09-12 19:23:45 +00:00
uint32_t index = 0 ;
2008-03-14 16:21:13 +00:00
int my_id = 0 ;
2006-09-17 18:03:32 +00:00
switch_mutex_lock ( EVENT_QUEUE_MUTEX ) ;
2008-03-14 16:21:13 +00:00
THREAD_COUNT + + ;
switch_mutex_unlock ( EVENT_QUEUE_MUTEX ) ;
2007-03-29 22:31:56 +00:00
2008-03-17 16:25:53 +00:00
for ( my_id = 0 ; my_id < NUMBER_OF_QUEUES ; my_id + + ) {
2008-03-14 16:21:13 +00:00
if ( EVENT_QUEUE [ my_id ] = = queue ) {
break ;
}
}
2008-05-27 04:30:03 +00:00
for ( ; ; ) {
2008-03-14 16:21:13 +00:00
void * pop = NULL ;
switch_event_t * event = NULL ;
2011-04-15 16:18:26 +00:00
2008-03-14 16:21:13 +00:00
if ( switch_queue_pop ( queue , & pop ) ! = SWITCH_STATUS_SUCCESS ) {
break ;
2006-04-04 18:47:34 +00:00
}
2006-02-26 00:12:17 +00:00
2008-03-14 16:21:13 +00:00
if ( ! pop ) {
break ;
}
2008-03-14 03:47:45 +00:00
2009-02-20 01:10:59 +00:00
if ( ! SYSTEM_RUNNING ) {
break ;
}
2008-03-14 16:21:13 +00:00
event = ( switch_event_t * ) pop ;
2008-03-14 03:47:45 +00:00
2008-05-27 04:30:03 +00:00
while ( event ) {
2010-08-23 13:11:50 -05:00
2010-09-02 12:30:26 -05:00
for ( index = 0 ; index < SOFT_MAX_DISPATCH ; index + + ) {
2008-03-14 16:21:13 +00:00
if ( switch_queue_trypush ( EVENT_DISPATCH_QUEUE [ index ] , event ) = = SWITCH_STATUS_SUCCESS ) {
event = NULL ;
break ;
}
}
2008-05-27 04:30:03 +00:00
2008-03-14 16:21:13 +00:00
if ( event ) {
2008-05-27 04:30:03 +00:00
if ( SOFT_MAX_DISPATCH + 1 < MAX_DISPATCH ) {
2010-09-02 12:30:26 -05:00
switch_mutex_lock ( EVENT_QUEUE_MUTEX ) ;
2008-05-27 04:30:03 +00:00
launch_dispatch_threads ( SOFT_MAX_DISPATCH + 1 , DISPATCH_QUEUE_LEN , RUNTIME_POOL ) ;
2010-09-02 12:30:26 -05:00
switch_mutex_unlock ( EVENT_QUEUE_MUTEX ) ;
2010-08-23 13:11:50 -05:00
} else {
2012-05-03 16:31:21 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Out of event dispatch threads! Resorting to a blocking push.... Look for laggy event consumers or event_socket connections! \n " ) ;
switch_queue_push ( EVENT_DISPATCH_QUEUE [ 0 ] , event ) ;
2006-03-30 23:02:50 +00:00
}
2005-12-22 18:53:33 +00:00
}
2006-03-01 17:06:10 +00:00
}
2006-02-26 00:12:17 +00:00
}
2006-04-26 19:29:56 +00:00
2008-03-14 16:21:13 +00:00
switch_mutex_lock ( EVENT_QUEUE_MUTEX ) ;
THREAD_COUNT - - ;
switch_mutex_unlock ( EVENT_QUEUE_MUTEX ) ;
2008-05-27 04:30:03 +00:00
2008-03-14 16:21:13 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Event Thread %d Ended. \n " , my_id ) ;
2006-02-26 00:12:17 +00:00
return NULL ;
2008-05-27 04:30:03 +00:00
2006-02-26 00:12:17 +00:00
}
2005-12-14 20:22:19 +00:00
2008-03-14 16:21:13 +00:00
2006-04-29 01:00:52 +00:00
SWITCH_DECLARE ( void ) switch_event_deliver ( switch_event_t * * event )
2006-02-26 00:12:17 +00:00
{
2006-04-29 01:00:52 +00:00
switch_event_types_t e ;
2006-04-29 06:05:03 +00:00
switch_event_node_t * node ;
2006-01-03 01:17:59 +00:00
2009-02-20 01:10:59 +00:00
if ( SYSTEM_RUNNING ) {
switch_thread_rwlock_rdlock ( RWLOCK ) ;
for ( e = ( * event ) - > event_id ; ; e = SWITCH_EVENT_ALL ) {
for ( node = EVENT_NODES [ e ] ; node ; node = node - > next ) {
if ( switch_events_match ( * event , node ) ) {
( * event ) - > bind_user_data = node - > user_data ;
node - > callback ( * event ) ;
}
}
2010-02-06 03:38:24 +00:00
2009-02-20 01:10:59 +00:00
if ( e = = SWITCH_EVENT_ALL ) {
break ;
2005-12-14 20:22:19 +00:00
}
}
2009-02-20 01:10:59 +00:00
switch_thread_rwlock_unlock ( RWLOCK ) ;
2005-12-14 20:22:19 +00:00
}
2006-02-26 00:12:17 +00:00
switch_event_destroy ( event ) ;
2005-12-14 20:22:19 +00:00
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_running ( void )
2005-12-21 22:25:22 +00:00
{
2008-03-14 16:21:13 +00:00
return SYSTEM_RUNNING ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE ;
2005-12-21 22:25:22 +00:00
}
2005-12-15 19:10:43 +00:00
2008-05-12 16:58:44 +00:00
SWITCH_DECLARE ( const char * ) switch_event_name ( switch_event_types_t event )
2005-12-13 20:52:33 +00:00
{
2007-12-11 19:23:57 +00:00
switch_assert ( BLOCK ! = NULL ) ;
switch_assert ( RUNTIME_POOL ! = NULL ) ;
2005-12-14 20:22:19 +00:00
2005-12-13 20:52:33 +00:00
return EVENT_NAMES [ event ] ;
}
2008-01-12 07:14:48 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_name_event ( const char * name , switch_event_types_t * type )
2006-07-22 21:49:52 +00:00
{
switch_event_types_t x ;
2007-12-11 19:23:57 +00:00
switch_assert ( BLOCK ! = NULL ) ;
switch_assert ( RUNTIME_POOL ! = NULL ) ;
2007-03-29 22:31:56 +00:00
2006-07-22 21:49:52 +00:00
for ( x = 0 ; x < = SWITCH_EVENT_ALL ; x + + ) {
2010-06-07 08:49:04 -04:00
if ( ( strlen ( name ) > 13 & & ! strcasecmp ( name + 13 , EVENT_NAMES [ x ] ) ) | | ! strcasecmp ( name , EVENT_NAMES [ x ] ) ) {
2006-07-22 21:49:52 +00:00
* type = x ;
return SWITCH_STATUS_SUCCESS ;
}
}
2007-03-29 22:31:56 +00:00
2006-07-22 21:49:52 +00:00
return SWITCH_STATUS_FALSE ;
}
2008-07-01 23:41:09 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_free_subclass_detailed ( const char * owner , const char * subclass_name )
{
switch_event_subclass_t * subclass ;
switch_status_t status = SWITCH_STATUS_FALSE ;
switch_assert ( RUNTIME_POOL ! = NULL ) ;
switch_assert ( CUSTOM_HASH ! = NULL ) ;
if ( ( subclass = switch_core_hash_find ( CUSTOM_HASH , subclass_name ) ) ) {
if ( ! strcmp ( owner , subclass - > owner ) ) {
switch_thread_rwlock_wrlock ( RWLOCK ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Subclass reservation deleted for %s:%s \n " , owner , subclass_name ) ;
switch_core_hash_delete ( CUSTOM_HASH , subclass_name ) ;
FREE ( subclass - > owner ) ;
FREE ( subclass - > name ) ;
FREE ( subclass ) ;
status = SWITCH_STATUS_SUCCESS ;
switch_thread_rwlock_unlock ( RWLOCK ) ;
2009-12-04 20:28:55 +00:00
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Subclass reservation %s inuse by listeners, detaching.. \n " , subclass_name ) ;
subclass - > bind = 1 ;
2008-07-01 23:41:09 +00:00
}
}
2010-02-06 03:38:24 +00:00
2008-07-01 23:41:09 +00:00
return status ;
}
2008-01-12 07:14:48 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_reserve_subclass_detailed ( const char * owner , const char * subclass_name )
2005-12-14 22:46:09 +00:00
{
2006-04-29 06:05:03 +00:00
switch_event_subclass_t * subclass ;
2010-02-06 03:38:24 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( RUNTIME_POOL ! = NULL ) ;
switch_assert ( CUSTOM_HASH ! = NULL ) ;
2005-12-14 22:46:09 +00:00
2009-12-04 20:28:55 +00:00
if ( ( subclass = switch_core_hash_find ( CUSTOM_HASH , subclass_name ) ) ) {
/* a listener reserved it for us, now we can lock it so nobody else can have it */
2010-02-06 03:38:24 +00:00
if ( subclass - > bind ) {
2009-12-04 20:28:55 +00:00
subclass - > bind = 0 ;
return SWITCH_STATUS_SUCCESS ;
}
2005-12-14 22:46:09 +00:00
return SWITCH_STATUS_INUSE ;
}
2005-12-15 19:10:43 +00:00
2008-07-01 23:41:09 +00:00
switch_zmalloc ( subclass , sizeof ( * subclass ) ) ;
2006-01-03 01:17:59 +00:00
2008-07-01 23:41:09 +00:00
subclass - > owner = DUP ( owner ) ;
subclass - > name = DUP ( subclass_name ) ;
2010-02-06 03:38:24 +00:00
more event stuff
you should now be able to bind an event handler to a
paticiular file or function not just a paticular event
when using the custom event
like "file:somefile.c"
or "func:somefunc"
also events now have headers which can be added
with varargs and should be created and delivered with api calls
switch_event *event;
regular event:
if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "System Ready");
switch_event_fire(&event);
}
custom event:
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "some_subclass_string") == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "hello world %d", 42);
switch_event_fire(&event);
}
switch_event_add_header(event, "test %d", 42);
also you can serialize and event into a buffer in
a printable/transferrable format with optional body
char buf[1024];
with body:
switch_event_serialize(event, buf, sizeof(buf), "This is a body my favorite number is %d", 42);
no body:
switch_event_serialize(event, buf, sizeof(buf), NULL);
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@173 d0543943-73ff-0310-b7d9-9358b9ac24b2
2005-12-19 19:57:32 +00:00
switch_core_hash_insert ( CUSTOM_HASH , subclass - > name , subclass ) ;
2006-01-03 01:17:59 +00:00
2005-12-14 22:46:09 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-10-04 17:25:06 +00:00
SWITCH_DECLARE ( void ) switch_core_memory_reclaim_events ( void )
{
2009-02-26 22:30:00 +00:00
# ifdef SWITCH_EVENT_RECYCLE
2007-10-04 17:25:06 +00:00
void * pop ;
2007-10-04 20:22:37 +00:00
int size ;
size = switch_queue_size ( EVENT_RECYCLE_QUEUE ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Returning %d recycled event(s) %d bytes \n " , size , ( int ) sizeof ( switch_event_t ) * size ) ;
size = switch_queue_size ( EVENT_HEADER_RECYCLE_QUEUE ) ;
2008-05-27 04:30:03 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Returning %d recycled event header(s) %d bytes \n " ,
2007-10-04 20:22:37 +00:00
size , ( int ) sizeof ( switch_event_header_t ) * size ) ;
2009-02-20 01:10:59 +00:00
while ( switch_queue_trypop ( EVENT_HEADER_RECYCLE_QUEUE , & pop ) = = SWITCH_STATUS_SUCCESS & & pop ) {
2007-10-04 17:25:06 +00:00
free ( pop ) ;
}
2009-02-20 01:10:59 +00:00
while ( switch_queue_trypop ( EVENT_RECYCLE_QUEUE , & pop ) = = SWITCH_STATUS_SUCCESS & & pop ) {
2007-10-04 17:25:06 +00:00
free ( pop ) ;
}
2009-02-26 22:30:00 +00:00
# else
return ;
# endif
2007-10-04 17:25:06 +00:00
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_shutdown ( void )
2005-12-14 20:22:19 +00:00
{
2008-09-12 18:04:58 +00:00
uint32_t x = 0 ;
int last = 0 ;
2008-08-22 17:00:16 +00:00
switch_hash_index_t * hi ;
const void * var ;
2010-02-06 03:38:24 +00:00
void * val ;
2007-10-04 17:25:06 +00:00
2008-03-14 16:21:13 +00:00
switch_mutex_lock ( EVENT_QUEUE_MUTEX ) ;
SYSTEM_RUNNING = 0 ;
switch_mutex_unlock ( EVENT_QUEUE_MUTEX ) ;
2006-09-17 18:03:32 +00:00
2008-05-27 04:30:03 +00:00
for ( x = 0 ; x < 3 ; x + + ) {
2012-05-03 16:31:21 -05:00
if ( EVENT_QUEUE [ x ] ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Stopping event queue %d \n " , x ) ;
switch_queue_trypush ( EVENT_QUEUE [ x ] , NULL ) ;
switch_queue_interrupt_all ( EVENT_QUEUE [ x ] ) ;
}
2008-03-14 16:21:13 +00:00
}
2008-03-14 03:47:45 +00:00
2008-05-27 04:30:03 +00:00
for ( x = 0 ; x < SOFT_MAX_DISPATCH ; x + + ) {
2008-03-14 16:21:13 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Stopping dispatch queue %d \n " , x ) ;
2009-02-20 01:10:59 +00:00
switch_queue_trypush ( EVENT_DISPATCH_QUEUE [ x ] , NULL ) ;
switch_queue_interrupt_all ( EVENT_DISPATCH_QUEUE [ x ] ) ;
2008-03-14 16:21:13 +00:00
}
2008-05-27 04:30:03 +00:00
2008-03-14 16:21:13 +00:00
while ( x < 10000 & & THREAD_COUNT ) {
2008-11-14 23:31:21 +00:00
switch_cond_next ( ) ;
2008-03-14 16:21:13 +00:00
if ( THREAD_COUNT = = last ) {
x + + ;
2006-03-01 17:06:10 +00:00
}
2008-03-14 16:21:13 +00:00
last = THREAD_COUNT ;
2005-12-14 20:22:19 +00:00
}
2010-02-06 03:38:24 +00:00
2009-02-20 01:10:59 +00:00
for ( x = 0 ; x < SOFT_MAX_DISPATCH ; x + + ) {
void * pop = NULL ;
2010-02-06 03:38:24 +00:00
switch_event_t * event = NULL ;
2009-02-20 01:10:59 +00:00
switch_status_t st ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Stopping dispatch thread %d \n " , x ) ;
switch_thread_join ( & st , EVENT_DISPATCH_QUEUE_THREADS [ x ] ) ;
while ( switch_queue_trypop ( EVENT_DISPATCH_QUEUE [ x ] , & pop ) = = SWITCH_STATUS_SUCCESS & & pop ) {
event = ( switch_event_t * ) pop ;
switch_event_destroy ( & event ) ;
2010-02-06 03:38:24 +00:00
}
2009-02-20 01:10:59 +00:00
}
2008-05-27 04:30:03 +00:00
2009-02-20 01:10:59 +00:00
for ( x = 0 ; x < NUMBER_OF_QUEUES ; x + + ) {
void * pop = NULL ;
2010-02-06 03:38:24 +00:00
switch_event_t * event = NULL ;
2009-02-20 01:10:59 +00:00
switch_status_t st ;
2012-05-03 16:31:21 -05:00
if ( EVENT_QUEUE_THREADS [ x ] ) {
2009-02-20 01:10:59 +00:00
2012-05-03 16:31:21 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CONSOLE , " Stopping queue thread %d \n " , x ) ;
switch_thread_join ( & st , EVENT_QUEUE_THREADS [ x ] ) ;
while ( switch_queue_trypop ( EVENT_QUEUE [ x ] , & pop ) = = SWITCH_STATUS_SUCCESS & & pop ) {
event = ( switch_event_t * ) pop ;
switch_event_destroy ( & event ) ;
}
2010-02-06 03:38:24 +00:00
}
2009-02-20 01:10:59 +00:00
}
2010-02-06 03:38:24 +00:00
2008-08-22 17:00:16 +00:00
for ( hi = switch_hash_first ( NULL , CUSTOM_HASH ) ; hi ; hi = switch_hash_next ( hi ) ) {
switch_event_subclass_t * subclass ;
2008-08-22 17:57:15 +00:00
switch_hash_this ( hi , & var , NULL , & val ) ;
2008-08-22 17:00:16 +00:00
if ( ( subclass = ( switch_event_subclass_t * ) val ) ) {
FREE ( subclass - > name ) ;
FREE ( subclass - > owner ) ;
FREE ( subclass ) ;
}
}
2007-09-29 01:06:08 +00:00
switch_core_hash_destroy ( & CUSTOM_HASH ) ;
2007-10-04 17:25:06 +00:00
switch_core_memory_reclaim_events ( ) ;
2007-09-29 01:06:08 +00:00
2005-12-14 20:22:19 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-09-12 19:23:45 +00:00
static void launch_dispatch_threads ( uint32_t max , int len , switch_memory_pool_t * pool )
2008-03-14 03:47:45 +00:00
{
2008-05-27 04:30:03 +00:00
switch_threadattr_t * thd_attr ;
2008-09-12 18:04:58 +00:00
uint32_t index = 0 ;
2010-09-02 12:30:26 -05:00
int launched = 0 ;
uint32_t sanity = 200 ;
2008-03-14 03:47:45 +00:00
if ( max > MAX_DISPATCH ) {
return ;
}
2008-05-27 04:30:03 +00:00
2008-03-14 03:47:45 +00:00
if ( max < SOFT_MAX_DISPATCH ) {
return ;
}
2008-05-27 04:30:03 +00:00
2008-03-14 03:47:45 +00:00
for ( index = SOFT_MAX_DISPATCH ; index < max & & index < MAX_DISPATCH ; index + + ) {
if ( EVENT_DISPATCH_QUEUE [ index ] ) {
continue ;
}
switch_queue_create ( & EVENT_DISPATCH_QUEUE [ index ] , len , pool ) ;
switch_threadattr_create ( & thd_attr , pool ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
switch_threadattr_priority_increase ( thd_attr ) ;
2009-02-20 01:10:59 +00:00
switch_thread_create ( & EVENT_DISPATCH_QUEUE_THREADS [ index ] , thd_attr , switch_event_dispatch_thread , EVENT_DISPATCH_QUEUE [ index ] , pool ) ;
2010-09-02 12:30:26 -05:00
while ( - - sanity & & ! EVENT_DISPATCH_QUEUE_RUNNING [ index ] ) switch_yield ( 10000 ) ;
2012-05-03 16:31:21 -05:00
if ( index = = 1 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Create event dispatch thread %d \n " , index ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Create additional event dispatch thread %d \n " , index ) ;
}
2010-09-02 12:30:26 -05:00
launched + + ;
break ;
2008-03-14 03:47:45 +00:00
}
SOFT_MAX_DISPATCH = index ;
}
2007-03-30 00:15:25 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_init ( switch_memory_pool_t * pool )
2005-12-13 20:52:33 +00:00
{
2012-05-03 16:31:21 -05:00
//switch_threadattr_t *thd_attr;
2008-05-16 16:59:34 +00:00
2010-07-01 18:14:44 -05:00
/*
This statement doesn ' t do anything commenting it out for now .
switch_assert ( switch_arraylen ( EVENT_NAMES ) = = SWITCH_EVENT_ALL + 1 ) ;
*/
2012-05-03 16:31:21 -05:00
/* don't need any more dispatch threads than we have CPU's*/
MAX_DISPATCH = switch_core_cpu_count ( ) ;
2010-06-07 08:49:04 -04:00
2008-05-16 16:59:34 +00:00
switch_assert ( pool ! = NULL ) ;
2009-02-20 01:10:59 +00:00
THRUNTIME_POOL = RUNTIME_POOL = pool ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Activate Eventing Engine. \n " ) ;
switch_thread_rwlock_create ( & RWLOCK , RUNTIME_POOL ) ;
switch_mutex_init ( & BLOCK , SWITCH_MUTEX_NESTED , RUNTIME_POOL ) ;
switch_mutex_init ( & POOL_LOCK , SWITCH_MUTEX_NESTED , RUNTIME_POOL ) ;
switch_mutex_init ( & EVENT_QUEUE_MUTEX , SWITCH_MUTEX_NESTED , RUNTIME_POOL ) ;
switch_core_hash_init ( & CUSTOM_HASH , RUNTIME_POOL ) ;
switch_mutex_lock ( EVENT_QUEUE_MUTEX ) ;
SYSTEM_RUNNING = - 1 ;
switch_mutex_unlock ( EVENT_QUEUE_MUTEX ) ;
2008-05-16 16:59:34 +00:00
2012-05-03 16:31:21 -05:00
//switch_threadattr_create(&thd_attr, pool);
2009-06-02 16:55:10 +00:00
switch_find_local_ip ( guess_ip_v4 , sizeof ( guess_ip_v4 ) , NULL , AF_INET ) ;
switch_find_local_ip ( guess_ip_v6 , sizeof ( guess_ip_v6 ) , NULL , AF_INET6 ) ;
2005-12-14 20:22:19 +00:00
2005-12-22 18:53:33 +00:00
2012-05-03 16:31:21 -05:00
//switch_queue_create(&EVENT_QUEUE[0], POOL_COUNT_MAX + 10, THRUNTIME_POOL);
//switch_queue_create(&EVENT_QUEUE[1], POOL_COUNT_MAX + 10, THRUNTIME_POOL);
//switch_queue_create(&EVENT_QUEUE[2], POOL_COUNT_MAX + 10, THRUNTIME_POOL);
2009-02-26 22:30:00 +00:00
# ifdef SWITCH_EVENT_RECYCLE
2008-03-08 02:11:21 +00:00
switch_queue_create ( & EVENT_RECYCLE_QUEUE , 250000 , THRUNTIME_POOL ) ;
switch_queue_create ( & EVENT_HEADER_RECYCLE_QUEUE , 250000 , THRUNTIME_POOL ) ;
2009-02-26 22:30:00 +00:00
# endif
2008-05-27 04:30:03 +00:00
2012-05-03 16:31:21 -05:00
//switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
//switch_threadattr_priority_increase(thd_attr);
2008-03-14 03:47:45 +00:00
launch_dispatch_threads ( 1 , DISPATCH_QUEUE_LEN , RUNTIME_POOL ) ;
2012-05-03 16:31:21 -05:00
//switch_thread_create(&EVENT_QUEUE_THREADS[0], thd_attr, switch_event_thread, EVENT_QUEUE[0], RUNTIME_POOL);
//switch_thread_create(&EVENT_QUEUE_THREADS[1], thd_attr, switch_event_thread, EVENT_QUEUE[1], RUNTIME_POOL);
//switch_thread_create(&EVENT_QUEUE_THREADS[2], thd_attr, switch_event_thread, EVENT_QUEUE[2], RUNTIME_POOL);
2008-05-27 04:30:03 +00:00
2008-03-14 16:21:13 +00:00
while ( ! THREAD_COUNT ) {
2008-11-14 23:31:21 +00:00
switch_cond_next ( ) ;
2005-12-14 21:29:46 +00:00
}
2008-03-14 16:21:13 +00:00
switch_mutex_lock ( EVENT_QUEUE_MUTEX ) ;
SYSTEM_RUNNING = 1 ;
switch_mutex_unlock ( EVENT_QUEUE_MUTEX ) ;
2005-12-14 20:22:19 +00:00
return SWITCH_STATUS_SUCCESS ;
2005-12-13 20:52:33 +00:00
}
2009-02-21 23:19:58 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_create_subclass_detailed ( const char * file , const char * func , int line ,
switch_event_t * * event , switch_event_types_t event_id , const char * subclass_name )
2005-12-13 20:52:33 +00:00
{
2009-02-26 22:30:00 +00:00
# ifdef SWITCH_EVENT_RECYCLE
2007-09-30 20:05:18 +00:00
void * pop ;
2009-02-26 22:30:00 +00:00
# endif
2008-05-27 04:30:03 +00:00
2008-10-07 17:09:31 +00:00
* event = NULL ;
2009-02-26 18:54:00 +00:00
if ( ( event_id ! = SWITCH_EVENT_CLONE & & event_id ! = SWITCH_EVENT_CUSTOM ) & & subclass_name ) {
2005-12-19 18:55:31 +00:00
return SWITCH_STATUS_GENERR ;
}
2009-02-26 22:30:00 +00:00
# ifdef SWITCH_EVENT_RECYCLE
2011-07-11 17:41:14 -05:00
if ( EVENT_RECYCLE_QUEUE & & switch_queue_trypop ( EVENT_RECYCLE_QUEUE , & pop ) = = SWITCH_STATUS_SUCCESS & & pop ) {
2007-09-30 20:05:18 +00:00
* event = ( switch_event_t * ) pop ;
} else {
2009-02-26 22:30:00 +00:00
# endif
2007-09-30 20:05:18 +00:00
* event = ALLOC ( sizeof ( switch_event_t ) ) ;
2007-12-11 19:23:57 +00:00
switch_assert ( * event ) ;
2009-02-26 22:30:00 +00:00
# ifdef SWITCH_EVENT_RECYCLE
2005-12-13 20:52:33 +00:00
}
2009-02-26 22:30:00 +00:00
# endif
2007-09-30 20:05:18 +00:00
2006-04-29 01:00:52 +00:00
memset ( * event , 0 , sizeof ( switch_event_t ) ) ;
more event stuff
you should now be able to bind an event handler to a
paticiular file or function not just a paticular event
when using the custom event
like "file:somefile.c"
or "func:somefunc"
also events now have headers which can be added
with varargs and should be created and delivered with api calls
switch_event *event;
regular event:
if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "System Ready");
switch_event_fire(&event);
}
custom event:
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "some_subclass_string") == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "hello world %d", 42);
switch_event_fire(&event);
}
switch_event_add_header(event, "test %d", 42);
also you can serialize and event into a buffer in
a printable/transferrable format with optional body
char buf[1024];
with body:
switch_event_serialize(event, buf, sizeof(buf), "This is a body my favorite number is %d", 42);
no body:
switch_event_serialize(event, buf, sizeof(buf), NULL);
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@173 d0543943-73ff-0310-b7d9-9358b9ac24b2
2005-12-19 19:57:32 +00:00
2011-09-21 14:31:10 -05:00
if ( event_id = = SWITCH_EVENT_REQUEST_PARAMS | | event_id = = SWITCH_EVENT_CHANNEL_DATA | | event_id = = SWITCH_EVENT_MESSAGE ) {
2009-09-17 21:38:04 +00:00
( * event ) - > flags | = EF_UNIQ_HEADERS ;
}
2009-02-26 18:54:00 +00:00
if ( event_id ! = SWITCH_EVENT_CLONE ) {
2009-02-26 00:38:14 +00:00
( * event ) - > event_id = event_id ;
switch_event_prep_for_delivery_detailed ( file , func , line , * event ) ;
}
2009-02-21 23:19:58 +00:00
more event stuff
you should now be able to bind an event handler to a
paticiular file or function not just a paticular event
when using the custom event
like "file:somefile.c"
or "func:somefunc"
also events now have headers which can be added
with varargs and should be created and delivered with api calls
switch_event *event;
regular event:
if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "System Ready");
switch_event_fire(&event);
}
custom event:
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "some_subclass_string") == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "hello world %d", 42);
switch_event_fire(&event);
}
switch_event_add_header(event, "test %d", 42);
also you can serialize and event into a buffer in
a printable/transferrable format with optional body
char buf[1024];
with body:
switch_event_serialize(event, buf, sizeof(buf), "This is a body my favorite number is %d", 42);
no body:
switch_event_serialize(event, buf, sizeof(buf), NULL);
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@173 d0543943-73ff-0310-b7d9-9358b9ac24b2
2005-12-19 19:57:32 +00:00
if ( subclass_name ) {
2008-07-01 23:41:09 +00:00
( * event ) - > subclass_name = DUP ( subclass_name ) ;
2008-01-03 01:21:26 +00:00
switch_event_add_header_string ( * event , SWITCH_STACK_BOTTOM , " Event-Subclass " , subclass_name ) ;
more event stuff
you should now be able to bind an event handler to a
paticiular file or function not just a paticular event
when using the custom event
like "file:somefile.c"
or "func:somefunc"
also events now have headers which can be added
with varargs and should be created and delivered with api calls
switch_event *event;
regular event:
if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "System Ready");
switch_event_fire(&event);
}
custom event:
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "some_subclass_string") == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "hello world %d", 42);
switch_event_fire(&event);
}
switch_event_add_header(event, "test %d", 42);
also you can serialize and event into a buffer in
a printable/transferrable format with optional body
char buf[1024];
with body:
switch_event_serialize(event, buf, sizeof(buf), "This is a body my favorite number is %d", 42);
no body:
switch_event_serialize(event, buf, sizeof(buf), NULL);
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@173 d0543943-73ff-0310-b7d9-9358b9ac24b2
2005-12-19 19:57:32 +00:00
}
2005-12-19 18:55:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_set_priority ( switch_event_t * event , switch_priority_t priority )
2006-02-26 00:12:17 +00:00
{
event - > priority = priority ;
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_TOP , " priority " , switch_priority_name ( priority ) ) ;
2006-02-26 00:12:17 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2011-09-21 14:31:10 -05:00
SWITCH_DECLARE ( switch_status_t ) switch_event_rename_header ( switch_event_t * event , const char * header_name , const char * new_header_name )
{
switch_event_header_t * hp ;
switch_ssize_t hlen = - 1 ;
unsigned long hash = 0 ;
int x = 0 ;
switch_assert ( event ) ;
if ( ! header_name ) {
return SWITCH_STATUS_FALSE ;
}
hash = switch_ci_hashfunc_default ( header_name , & hlen ) ;
for ( hp = event - > headers ; hp ; hp = hp - > next ) {
if ( ( ! hp - > hash | | hash = = hp - > hash ) & & ! strcasecmp ( hp - > name , header_name ) ) {
FREE ( hp - > name ) ;
hp - > name = DUP ( new_header_name ) ;
hlen = - 1 ;
hp - > hash = switch_ci_hashfunc_default ( hp - > name , & hlen ) ;
x + + ;
}
}
return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE ;
}
2011-05-25 15:42:36 -05:00
SWITCH_DECLARE ( switch_event_header_t * ) switch_event_get_header_ptr ( switch_event_t * event , const char * header_name )
2005-12-19 18:55:31 +00:00
{
2006-04-29 01:00:52 +00:00
switch_event_header_t * hp ;
2008-11-03 20:08:44 +00:00
switch_ssize_t hlen = - 1 ;
unsigned long hash = 0 ;
2008-05-06 21:43:42 +00:00
switch_assert ( event ) ;
2008-01-29 19:01:35 +00:00
2010-02-06 03:38:24 +00:00
if ( ! header_name )
return NULL ;
2008-11-03 20:08:44 +00:00
hash = switch_ci_hashfunc_default ( header_name , & hlen ) ;
2010-02-06 03:38:24 +00:00
2008-01-29 19:01:35 +00:00
for ( hp = event - > headers ; hp ; hp = hp - > next ) {
2010-02-06 03:38:24 +00:00
if ( ( ! hp - > hash | | hash = = hp - > hash ) & & ! strcasecmp ( hp - > name , header_name ) ) {
2011-05-25 15:42:36 -05:00
return hp ;
2005-12-19 18:55:31 +00:00
}
}
return NULL ;
}
2011-05-25 15:42:36 -05:00
SWITCH_DECLARE ( char * ) switch_event_get_header_idx ( switch_event_t * event , const char * header_name , int idx )
{
switch_event_header_t * hp ;
if ( ( hp = switch_event_get_header_ptr ( event , header_name ) ) ) {
if ( idx > - 1 ) {
if ( idx < hp - > idx ) {
return hp - > array [ idx ] ;
} else {
return NULL ;
}
}
return hp - > value ;
2011-09-21 14:31:10 -05:00
} else if ( ! strcmp ( header_name , " _body " ) ) {
return event - > body ;
2011-05-25 15:42:36 -05:00
}
return NULL ;
}
2006-08-18 01:28:50 +00:00
SWITCH_DECLARE ( char * ) switch_event_get_body ( switch_event_t * event )
{
2008-01-29 19:01:35 +00:00
return ( event ? event - > body : NULL ) ;
2006-08-18 01:28:50 +00:00
}
2010-01-28 01:00:04 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_del_header_val ( switch_event_t * event , const char * header_name , const char * val )
2007-09-29 01:06:08 +00:00
{
2008-10-30 00:39:55 +00:00
switch_event_header_t * hp , * lp = NULL , * tp ;
2007-09-29 01:06:08 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2007-12-21 18:15:33 +00:00
int x = 0 ;
2008-11-03 20:08:44 +00:00
switch_ssize_t hlen = - 1 ;
unsigned long hash = 0 ;
2008-10-30 00:39:55 +00:00
tp = event - > headers ;
while ( tp ) {
hp = tp ;
tp = tp - > next ;
2010-02-06 03:38:24 +00:00
2007-12-21 18:15:33 +00:00
x + + ;
2011-01-13 10:03:00 -06:00
switch_assert ( x < 1000000 ) ;
2008-11-03 20:08:44 +00:00
hash = switch_ci_hashfunc_default ( header_name , & hlen ) ;
2010-01-28 01:00:04 +00:00
if ( ( ! hp - > hash | | hash = = hp - > hash ) & & ! strcasecmp ( header_name , hp - > name ) & & ( zstr ( val ) | | ! strcmp ( hp - > value , val ) ) ) {
2007-09-29 01:06:08 +00:00
if ( lp ) {
lp - > next = hp - > next ;
} else {
event - > headers = hp - > next ;
}
2008-01-03 21:34:44 +00:00
if ( hp = = event - > last_header | | ! hp - > next ) {
event - > last_header = lp ;
}
2007-09-29 01:06:08 +00:00
FREE ( hp - > name ) ;
2011-05-25 15:42:36 -05:00
if ( hp - > idx ) {
int i = 0 ;
for ( i = 0 ; i < hp - > idx ; i + + ) {
FREE ( hp - > array [ i ] ) ;
}
FREE ( hp - > array ) ;
}
2007-09-29 01:06:08 +00:00
FREE ( hp - > value ) ;
2011-05-25 15:42:36 -05:00
2007-12-21 18:15:33 +00:00
memset ( hp , 0 , sizeof ( * hp ) ) ;
2009-02-26 22:30:00 +00:00
# ifdef SWITCH_EVENT_RECYCLE
2007-10-04 17:25:06 +00:00
if ( switch_queue_trypush ( EVENT_HEADER_RECYCLE_QUEUE , hp ) ! = SWITCH_STATUS_SUCCESS ) {
FREE ( hp ) ;
}
2009-02-26 22:30:00 +00:00
# else
FREE ( hp ) ;
# endif
2007-09-29 01:06:08 +00:00
status = SWITCH_STATUS_SUCCESS ;
2008-10-30 00:39:55 +00:00
} else {
lp = hp ;
2007-09-29 01:06:08 +00:00
}
}
2008-05-27 04:30:03 +00:00
2007-09-29 01:06:08 +00:00
return status ;
}
2011-05-26 09:55:41 -05:00
static switch_event_header_t * new_header ( const char * header_name )
{
switch_event_header_t * header ;
# ifdef SWITCH_EVENT_RECYCLE
void * pop ;
2011-07-11 17:41:14 -05:00
if ( EVENT_HEADER_RECYCLE_QUEUE & & switch_queue_trypop ( EVENT_HEADER_RECYCLE_QUEUE , & pop ) = = SWITCH_STATUS_SUCCESS ) {
2011-05-26 09:55:41 -05:00
header = ( switch_event_header_t * ) pop ;
} else {
# endif
header = ALLOC ( sizeof ( * header ) ) ;
switch_assert ( header ) ;
# ifdef SWITCH_EVENT_RECYCLE
}
# endif
memset ( header , 0 , sizeof ( * header ) ) ;
header - > name = DUP ( header_name ) ;
return header ;
}
SWITCH_DECLARE ( int ) switch_event_add_array ( switch_event_t * event , const char * var , const char * val )
{
char * data ;
char * * array ;
int max = 0 ;
int len ;
const char * p ;
int i ;
if ( strlen ( val ) < 8 ) {
return - 1 ;
}
p = val + 7 ;
max = 1 ;
while ( ( p = strstr ( p , " |: " ) ) ) {
max + + ;
p + = 2 ;
}
if ( ! max ) {
return - 2 ;
}
data = strdup ( val + 7 ) ;
len = ( sizeof ( char * ) * max ) + 1 ;
2011-05-26 10:04:15 -05:00
switch_assert ( len ) ;
2011-05-26 09:55:41 -05:00
array = malloc ( len ) ;
memset ( array , 0 , len ) ;
2011-05-27 12:24:48 -04:00
switch_separate_string_string ( data , " |: " , array , max ) ;
2011-05-26 09:55:41 -05:00
for ( i = 0 ; i < max ; i + + ) {
switch_event_add_header_string ( event , SWITCH_STACK_PUSH , var , array [ i ] ) ;
}
free ( array ) ;
free ( data ) ;
return 0 ;
}
2011-05-25 15:42:36 -05:00
static switch_status_t switch_event_base_add_header ( switch_event_t * event , switch_stack_t stack , const char * header_name , char * data )
2008-01-03 01:21:26 +00:00
{
2011-05-25 15:42:36 -05:00
switch_event_header_t * header = NULL ;
2008-11-03 20:08:44 +00:00
switch_ssize_t hlen = - 1 ;
2011-05-25 15:42:36 -05:00
int exists = 0 , fly = 0 ;
char * index_ptr ;
int index = 0 ;
char * real_header_name = NULL ;
2011-09-21 14:31:10 -05:00
if ( ! strcmp ( header_name , " _body " ) ) {
switch_event_set_body ( event , data ) ;
}
2011-05-25 15:42:36 -05:00
if ( ( index_ptr = strchr ( header_name , ' [ ' ) ) ) {
index_ptr + + ;
index = atoi ( index_ptr ) ;
real_header_name = DUP ( header_name ) ;
if ( ( index_ptr = strchr ( real_header_name , ' [ ' ) ) ) {
* index_ptr + + = ' \0 ' ;
}
header_name = real_header_name ;
}
2011-05-31 09:53:39 -05:00
2011-05-26 09:55:41 -05:00
if ( index_ptr | | ( stack & SWITCH_STACK_PUSH ) | | ( stack & SWITCH_STACK_UNSHIFT ) ) {
2011-05-25 15:42:36 -05:00
if ( ! ( header = switch_event_get_header_ptr ( event , header_name ) ) & & index_ptr ) {
2011-05-26 09:55:41 -05:00
header = new_header ( header_name ) ;
2011-05-25 15:42:36 -05:00
if ( switch_test_flag ( event , EF_UNIQ_HEADERS ) ) {
switch_event_del_header ( event , header_name ) ;
}
2011-05-26 09:55:41 -05:00
2011-05-25 15:42:36 -05:00
fly + + ;
}
2011-05-26 09:55:41 -05:00
2011-05-25 15:42:36 -05:00
if ( ( header = switch_event_get_header_ptr ( event , header_name ) ) ) {
if ( index_ptr ) {
if ( index > - 1 & & index < = 4000 ) {
if ( index < header - > idx ) {
FREE ( header - > array [ index ] ) ;
header - > array [ index ] = DUP ( data ) ;
} else {
int i ;
char * * m ;
m = realloc ( header - > array , sizeof ( char * ) * ( index + 1 ) ) ;
switch_assert ( m ) ;
header - > array = m ;
for ( i = header - > idx ; i < index ; i + + ) {
m [ i ] = DUP ( " " ) ;
}
m [ index ] = DUP ( data ) ;
header - > idx = index + 1 ;
if ( ! fly ) {
exists = 1 ;
}
goto redraw ;
}
}
goto end ;
} else {
if ( ( stack & SWITCH_STACK_PUSH ) | | ( stack & SWITCH_STACK_UNSHIFT ) ) {
exists + + ;
stack & = ~ ( SWITCH_STACK_TOP | SWITCH_STACK_BOTTOM ) ;
} else {
header = NULL ;
}
}
}
}
2011-05-26 09:55:41 -05:00
if ( ! header ) {
2011-05-31 09:53:39 -05:00
if ( zstr ( data ) ) {
switch_event_del_header ( event , header_name ) ;
FREE ( data ) ;
goto end ;
}
2011-05-25 15:42:36 -05:00
if ( switch_test_flag ( event , EF_UNIQ_HEADERS ) ) {
switch_event_del_header ( event , header_name ) ;
}
2011-05-26 09:55:41 -05:00
if ( strstr ( data , " ARRAY:: " ) ) {
switch_event_add_array ( event , header_name , data ) ;
FREE ( data ) ;
goto end ;
}
2008-01-03 01:21:26 +00:00
2011-05-26 09:55:41 -05:00
header = new_header ( header_name ) ;
2009-09-17 21:38:04 +00:00
}
2011-05-25 15:42:36 -05:00
if ( ( stack & SWITCH_STACK_PUSH ) | | ( stack & SWITCH_STACK_UNSHIFT ) ) {
char * * m = NULL ;
switch_size_t len = 0 ;
char * hv ;
int i = 0 , j = 0 ;
if ( header - > value & & ! header - > idx ) {
m = malloc ( sizeof ( char * ) ) ;
switch_assert ( m ) ;
m [ 0 ] = header - > value ;
header - > value = NULL ;
header - > array = m ;
header - > idx + + ;
m = NULL ;
}
2009-09-17 21:38:04 +00:00
2011-05-25 15:42:36 -05:00
i = header - > idx + 1 ;
m = realloc ( header - > array , sizeof ( char * ) * i ) ;
switch_assert ( m ) ;
2008-01-03 01:21:26 +00:00
2011-05-25 15:42:36 -05:00
if ( ( stack & SWITCH_STACK_PUSH ) ) {
m [ header - > idx ] = data ;
} else if ( ( stack & SWITCH_STACK_UNSHIFT ) ) {
for ( j = header - > idx ; j > 0 ; j - - ) {
m [ j ] = m [ j - 1 ] ;
}
m [ 0 ] = data ;
}
2010-02-06 03:38:24 +00:00
2011-05-25 15:42:36 -05:00
header - > idx + + ;
header - > array = m ;
redraw :
2011-05-25 17:16:48 -05:00
len = 0 ;
2011-05-25 15:42:36 -05:00
for ( j = 0 ; j < header - > idx ; j + + ) {
len + = strlen ( header - > array [ j ] ) + 2 ;
}
if ( len ) {
len + = 8 ;
hv = realloc ( header - > value , len ) ;
switch_assert ( hv ) ;
header - > value = hv ;
switch_snprintf ( header - > value , len , " ARRAY:: " ) ;
for ( j = 0 ; j < header - > idx ; j + + ) {
2011-05-26 09:55:41 -05:00
switch_snprintf ( header - > value + strlen ( header - > value ) , len - strlen ( header - > value ) , " %s%s " , j = = 0 ? " " : " |: " , header - > array [ j ] ) ;
2011-05-25 15:42:36 -05:00
}
2008-01-03 01:21:26 +00:00
}
2011-05-25 15:42:36 -05:00
2008-01-03 01:21:26 +00:00
} else {
2011-05-25 15:42:36 -05:00
header - > value = data ;
}
if ( ! exists ) {
header - > hash = switch_ci_hashfunc_default ( header - > name , & hlen ) ;
if ( ( stack & SWITCH_STACK_TOP ) ) {
header - > next = event - > headers ;
2008-01-03 01:21:26 +00:00
event - > headers = header ;
2011-05-25 15:42:36 -05:00
if ( ! event - > last_header ) {
event - > last_header = header ;
}
} else {
if ( event - > last_header ) {
event - > last_header - > next = header ;
} else {
event - > headers = header ;
header - > next = NULL ;
}
event - > last_header = header ;
2008-01-03 01:21:26 +00:00
}
}
2011-05-25 15:42:36 -05:00
end :
switch_safe_free ( real_header_name ) ;
2008-01-03 01:21:26 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_add_header ( switch_event_t * event , switch_stack_t stack , const char * header_name , const char * fmt , . . . )
2005-12-19 18:55:31 +00:00
{
2006-01-03 01:17:59 +00:00
int ret = 0 ;
2007-09-29 01:06:08 +00:00
char * data ;
2006-01-03 01:17:59 +00:00
va_list ap ;
2007-09-29 01:06:08 +00:00
2005-12-19 18:55:31 +00:00
va_start ( ap , fmt ) ;
2007-09-29 01:06:08 +00:00
ret = switch_vasprintf ( & data , fmt , ap ) ;
2005-12-19 18:55:31 +00:00
va_end ( ap ) ;
2005-12-22 18:53:33 +00:00
2005-12-19 18:55:31 +00:00
if ( ret = = - 1 ) {
return SWITCH_STATUS_MEMERR ;
2008-01-03 01:21:26 +00:00
}
2006-03-29 19:11:20 +00:00
2008-01-03 01:21:26 +00:00
return switch_event_base_add_header ( event , stack , header_name , data ) ;
}
2005-12-19 18:55:31 +00:00
2009-07-24 20:13:36 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_set_subclass_name ( switch_event_t * event , const char * subclass_name )
{
2010-02-06 03:38:24 +00:00
if ( ! event | | ! subclass_name )
return SWITCH_STATUS_GENERR ;
2009-07-24 20:13:36 +00:00
switch_safe_free ( event - > subclass_name ) ;
event - > subclass_name = DUP ( subclass_name ) ;
switch_event_del_header ( event , " Event-Subclass " ) ;
2009-12-29 22:44:31 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Event-Subclass " , event - > subclass_name ) ;
2009-07-24 20:13:36 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-01-03 01:21:26 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_add_header_string ( switch_event_t * event , switch_stack_t stack , const char * header_name , const char * data )
{
if ( data ) {
2010-05-25 16:54:13 -05:00
return switch_event_base_add_header ( event , stack , header_name , ( stack & SWITCH_STACK_NODUP ) ? ( char * ) data : DUP ( data ) ) ;
2005-12-19 18:55:31 +00:00
}
2008-01-03 01:21:26 +00:00
return SWITCH_STATUS_GENERR ;
2005-12-19 18:55:31 +00:00
}
2011-09-21 14:31:10 -05:00
SWITCH_DECLARE ( switch_status_t ) switch_event_set_body ( switch_event_t * event , const char * body )
{
switch_safe_free ( event - > body ) ;
if ( body ) {
event - > body = DUP ( body ) ;
}
return SWITCH_STATUS_SUCCESS ;
}
2007-02-14 02:53:23 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_add_body ( switch_event_t * event , const char * fmt , . . . )
2005-12-23 02:24:56 +00:00
{
2006-01-03 01:17:59 +00:00
int ret = 0 ;
2007-02-03 17:06:57 +00:00
char * data ;
2005-12-23 02:24:56 +00:00
2006-01-03 01:17:59 +00:00
va_list ap ;
2006-08-15 15:57:20 +00:00
if ( fmt ) {
va_start ( ap , fmt ) ;
2007-03-09 20:44:13 +00:00
ret = switch_vasprintf ( & data , fmt , ap ) ;
2006-08-15 15:57:20 +00:00
va_end ( ap ) ;
2005-12-23 02:24:56 +00:00
2007-02-04 19:12:14 +00:00
if ( ret = = - 1 ) {
return SWITCH_STATUS_GENERR ;
} else {
2008-05-02 13:58:44 +00:00
switch_safe_free ( event - > body ) ;
2007-02-04 19:12:14 +00:00
event - > body = data ;
return SWITCH_STATUS_SUCCESS ;
}
2005-12-23 02:24:56 +00:00
} else {
2007-02-04 19:12:14 +00:00
return SWITCH_STATUS_GENERR ;
2005-12-23 02:24:56 +00:00
}
}
2006-04-29 01:00:52 +00:00
SWITCH_DECLARE ( void ) switch_event_destroy ( switch_event_t * * event )
2005-12-19 18:55:31 +00:00
{
2006-04-29 01:00:52 +00:00
switch_event_t * ep = * event ;
switch_event_header_t * hp , * this ;
2006-03-29 19:11:20 +00:00
2006-11-09 05:39:04 +00:00
if ( ep ) {
for ( hp = ep - > headers ; hp ; ) {
this = hp ;
hp = hp - > next ;
FREE ( this - > name ) ;
2011-05-25 15:42:36 -05:00
if ( this - > idx ) {
int i = 0 ;
2011-07-08 12:44:42 -05:00
2011-05-25 15:42:36 -05:00
for ( i = 0 ; i < this - > idx ; i + + ) {
FREE ( this - > array [ i ] ) ;
}
FREE ( this - > array ) ;
}
2006-11-09 05:39:04 +00:00
FREE ( this - > value ) ;
2011-05-25 15:42:36 -05:00
2009-02-26 22:30:00 +00:00
# ifdef SWITCH_EVENT_RECYCLE
2007-10-04 17:25:06 +00:00
if ( switch_queue_trypush ( EVENT_HEADER_RECYCLE_QUEUE , this ) ! = SWITCH_STATUS_SUCCESS ) {
FREE ( this ) ;
}
2009-02-26 22:30:00 +00:00
# else
FREE ( this ) ;
# endif
2006-11-09 05:39:04 +00:00
}
FREE ( ep - > body ) ;
2008-07-01 23:41:09 +00:00
FREE ( ep - > subclass_name ) ;
2009-02-26 22:30:00 +00:00
# ifdef SWITCH_EVENT_RECYCLE
2007-10-04 17:25:06 +00:00
if ( switch_queue_trypush ( EVENT_RECYCLE_QUEUE , ep ) ! = SWITCH_STATUS_SUCCESS ) {
FREE ( ep ) ;
}
2009-02-26 22:30:00 +00:00
# else
FREE ( ep ) ;
# endif
2006-03-29 19:11:20 +00:00
}
2005-12-19 18:55:31 +00:00
* event = NULL ;
}
2009-07-24 20:13:36 +00:00
2010-06-11 11:08:51 -05:00
SWITCH_DECLARE ( void ) switch_event_merge ( switch_event_t * event , switch_event_t * tomerge )
{
switch_event_header_t * hp ;
switch_assert ( tomerge & & event ) ;
for ( hp = tomerge - > headers ; hp ; hp = hp - > next ) {
2011-05-25 15:42:36 -05:00
if ( hp - > idx ) {
int i ;
for ( i = 0 ; i < hp - > idx ; i + + ) {
switch_event_add_header_string ( event , SWITCH_STACK_PUSH , hp - > name , hp - > array [ i ] ) ;
}
} else {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , hp - > name , hp - > value ) ;
}
2010-06-11 11:08:51 -05:00
}
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_dup ( switch_event_t * * event , switch_event_t * todup )
2005-12-19 18:55:31 +00:00
{
2009-02-26 00:38:14 +00:00
switch_event_header_t * hp ;
2005-12-19 18:55:31 +00:00
2009-02-26 18:54:00 +00:00
if ( switch_event_create_subclass ( event , SWITCH_EVENT_CLONE , todup - > subclass_name ) ! = SWITCH_STATUS_SUCCESS ) {
2005-12-19 18:55:31 +00:00
return SWITCH_STATUS_GENERR ;
}
2006-01-03 01:17:59 +00:00
2009-02-26 00:38:14 +00:00
( * event ) - > event_id = todup - > event_id ;
2005-12-21 16:24:37 +00:00
( * event ) - > event_user_data = todup - > event_user_data ;
( * event ) - > bind_user_data = todup - > bind_user_data ;
2010-06-11 11:08:51 -05:00
( * event ) - > flags = todup - > flags ;
2006-07-22 21:49:52 +00:00
for ( hp = todup - > headers ; hp ; hp = hp - > next ) {
2009-11-09 23:49:35 +00:00
if ( todup - > subclass_name & & ! strcmp ( hp - > name , " Event-Subclass " ) ) {
continue ;
}
2011-05-25 15:42:36 -05:00
if ( hp - > idx ) {
int i ;
for ( i = 0 ; i < hp - > idx ; i + + ) {
switch_event_add_header_string ( * event , SWITCH_STACK_PUSH , hp - > name , hp - > array [ i ] ) ;
}
} else {
switch_event_add_header_string ( * event , SWITCH_STACK_BOTTOM , hp - > name , hp - > value ) ;
}
2006-07-22 21:49:52 +00:00
}
if ( todup - > body ) {
( * event ) - > body = DUP ( todup - > body ) ;
2005-12-19 18:55:31 +00:00
}
2006-10-18 22:57:35 +00:00
( * event ) - > key = todup - > key ;
2005-12-19 18:55:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2011-09-21 14:31:10 -05:00
SWITCH_DECLARE ( switch_status_t ) switch_event_dup_reply ( switch_event_t * * event , switch_event_t * todup )
{
switch_event_header_t * hp ;
char hname [ 1024 ] = " " ;
char * p ;
if ( switch_event_create_subclass ( event , SWITCH_EVENT_CLONE , todup - > subclass_name ) ! = SWITCH_STATUS_SUCCESS ) {
return SWITCH_STATUS_GENERR ;
}
( * event ) - > event_id = todup - > event_id ;
( * event ) - > event_user_data = todup - > event_user_data ;
( * event ) - > bind_user_data = todup - > bind_user_data ;
( * event ) - > flags = todup - > flags ;
for ( hp = todup - > headers ; hp ; hp = hp - > next ) {
char * name = hp - > name , * value = hp - > value ;
if ( todup - > subclass_name & & ! strcmp ( hp - > name , " Event-Subclass " ) ) {
continue ;
}
if ( ! strncasecmp ( hp - > name , " from_ " , 5 ) ) {
p = hp - > name + 5 ;
switch_snprintf ( hname , sizeof ( hname ) , " to_%s " , p ) ;
name = hname ;
} else if ( ! strncasecmp ( hp - > name , " to_ " , 3 ) ) {
p = hp - > name + 3 ;
switch_snprintf ( hname , sizeof ( hname ) , " from_%s " , p ) ;
name = hname ;
} else if ( ! strcasecmp ( name , " to " ) ) {
name = " from " ;
} else if ( ! strcasecmp ( name , " from " ) ) {
name = " to " ;
}
if ( hp - > idx ) {
int i ;
for ( i = 0 ; i < hp - > idx ; i + + ) {
switch_event_add_header_string ( * event , SWITCH_STACK_PUSH , name , hp - > array [ i ] ) ;
}
} else {
switch_event_add_header_string ( * event , SWITCH_STACK_BOTTOM , name , value ) ;
}
}
switch_event_add_header_string ( * event , SWITCH_STACK_BOTTOM , " replying " , " true " ) ;
if ( todup - > body ) {
switch_event_add_header_string ( * event , SWITCH_STACK_BOTTOM , " orig_body " , todup - > body ) ;
}
( * event ) - > key = todup - > key ;
return SWITCH_STATUS_SUCCESS ;
}
2007-12-11 22:19:49 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_serialize ( switch_event_t * event , char * * str , switch_bool_t encode )
2005-12-19 18:55:31 +00:00
{
2006-03-30 23:02:50 +00:00
switch_size_t len = 0 ;
2006-04-29 01:00:52 +00:00
switch_event_header_t * hp ;
2006-12-15 18:02:54 +00:00
switch_size_t llen = 0 , dlen = 0 , blocksize = 512 , encode_len = 1536 , new_len = 0 ;
2006-11-11 19:32:45 +00:00
char * buf ;
2008-10-06 23:05:55 +00:00
char * encode_buf = NULL ; /* used for url encoding of variables to make sure unsafe things stay out of the serialized copy */
2007-03-29 22:31:56 +00:00
2006-11-11 19:32:45 +00:00
* str = NULL ;
2005-12-19 18:55:31 +00:00
2006-11-29 17:10:40 +00:00
dlen = blocksize * 2 ;
if ( ! ( buf = malloc ( dlen ) ) ) {
2011-05-25 15:42:36 -05:00
abort ( ) ;
2005-12-19 18:55:31 +00:00
}
2007-03-29 22:31:56 +00:00
/* go ahead and give ourselves some space to work with, should save a few reallocs */
if ( ! ( encode_buf = malloc ( encode_len ) ) ) {
2011-05-25 15:42:36 -05:00
abort ( ) ;
2007-03-29 22:31:56 +00:00
}
2006-11-29 04:57:01 +00:00
2008-10-06 23:05:55 +00:00
/* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "hit serialized!.\n"); */
2005-12-19 18:55:31 +00:00
for ( hp = event - > headers ; hp ; hp = hp - > next ) {
2007-03-29 22:31:56 +00:00
/*
* grab enough memory to store 3 x the string ( url encode takes one char and turns it into % XX )
2008-10-06 23:05:55 +00:00
* so we could end up with a string that is 3 times the originals length , unlikely but rather
2007-03-29 22:31:56 +00:00
* be safe than destroy the string , also add one for the null . And try to be smart about using
* the memory , allocate and only reallocate if we need more . This avoids an alloc , free CPU
* destroying loop .
*/
2011-05-25 15:42:36 -05:00
if ( hp - > idx ) {
int i ;
new_len = 0 ;
for ( i = 0 ; i < hp - > idx ; i + + ) {
new_len + = ( strlen ( hp - > array [ i ] ) * 3 ) + 1 ;
}
} else {
new_len = ( strlen ( hp - > value ) * 3 ) + 1 ;
}
2007-03-29 22:31:56 +00:00
if ( encode_len < new_len ) {
char * tmp ;
/* keep track of the size of our allocation */
encode_len = new_len ;
if ( ! ( tmp = realloc ( encode_buf , encode_len ) ) ) {
2011-05-25 15:42:36 -05:00
abort ( ) ;
2007-03-29 22:31:56 +00:00
}
encode_buf = tmp ;
}
/* handle any bad things in the string like newlines : etc that screw up the serialized format */
2011-05-25 15:42:36 -05:00
2007-12-11 22:19:49 +00:00
if ( encode ) {
2008-05-21 21:31:17 +00:00
switch_url_encode ( hp - > value , encode_buf , encode_len ) ;
2007-12-11 22:19:49 +00:00
} else {
2007-12-12 21:53:32 +00:00
switch_snprintf ( encode_buf , encode_len , " [%s] " , hp - > value ) ;
2007-12-11 22:19:49 +00:00
}
2006-11-29 04:57:01 +00:00
2011-05-25 15:42:36 -05:00
2006-12-15 18:02:54 +00:00
llen = strlen ( hp - > name ) + strlen ( encode_buf ) + 8 ;
2007-03-29 22:31:56 +00:00
2006-11-11 19:32:45 +00:00
if ( ( len + llen ) > dlen ) {
2011-06-01 22:36:19 -05:00
char * m = buf ;
2006-11-11 19:32:45 +00:00
dlen + = ( blocksize + ( len + llen ) ) ;
2011-06-01 22:36:19 -05:00
if ( ! ( buf = realloc ( buf , dlen ) ) ) {
2006-11-11 19:40:41 +00:00
buf = m ;
2011-05-25 15:42:36 -05:00
abort ( ) ;
2006-11-11 19:40:41 +00:00
}
2006-11-11 19:32:45 +00:00
}
2006-01-03 01:17:59 +00:00
2008-05-16 17:18:57 +00:00
switch_snprintf ( buf + len , dlen - len , " %s: %s \n " , hp - > name , * encode_buf = = ' \0 ' ? " _undef_ " : encode_buf ) ;
2006-11-11 19:32:45 +00:00
len = strlen ( buf ) ;
2005-12-15 19:10:43 +00:00
}
2005-12-23 02:24:56 +00:00
2007-03-29 22:31:56 +00:00
/* we are done with the memory we used for encoding, give it back */
switch_safe_free ( encode_buf ) ;
2006-11-29 04:57:01 +00:00
2006-11-11 19:32:45 +00:00
if ( event - > body ) {
int blen = ( int ) strlen ( event - > body ) ;
llen = blen ;
2005-12-23 02:24:56 +00:00
if ( blen ) {
2006-11-11 19:32:45 +00:00
llen + = 25 ;
2005-12-23 02:24:56 +00:00
} else {
2006-11-11 19:32:45 +00:00
llen + = 5 ;
}
2007-03-29 22:31:56 +00:00
2006-11-11 19:32:45 +00:00
if ( ( len + llen ) > dlen ) {
2011-06-01 22:36:19 -05:00
char * m = buf ;
2006-11-11 19:32:45 +00:00
dlen + = ( blocksize + ( len + llen ) ) ;
2011-06-01 22:36:19 -05:00
if ( ! ( buf = realloc ( buf , dlen ) ) ) {
2006-11-11 19:40:41 +00:00
buf = m ;
2011-05-25 15:42:36 -05:00
abort ( ) ;
2006-11-11 19:40:41 +00:00
}
2005-12-23 02:24:56 +00:00
}
2007-03-29 22:31:56 +00:00
2006-11-11 19:32:45 +00:00
if ( blen ) {
2007-12-12 21:53:32 +00:00
switch_snprintf ( buf + len , dlen - len , " Content-Length: %d \n \n %s " , blen , event - > body ) ;
2006-11-11 19:32:45 +00:00
} else {
2007-12-12 21:53:32 +00:00
switch_snprintf ( buf + len , dlen - len , " \n " ) ;
2006-11-11 19:32:45 +00:00
}
} else {
2007-12-12 21:53:32 +00:00
switch_snprintf ( buf + len , dlen - len , " \n " ) ;
2005-12-23 02:24:56 +00:00
}
2006-01-03 01:17:59 +00:00
2006-11-11 19:32:45 +00:00
* str = buf ;
2007-03-29 22:31:56 +00:00
2005-12-19 18:55:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2010-06-30 20:41:21 -05:00
2011-04-14 17:44:22 -05:00
SWITCH_DECLARE ( switch_status_t ) switch_event_create_brackets ( char * data , char a , char b , char c , switch_event_t * * event , char * * new_data , switch_bool_t dup )
2010-06-30 20:41:21 -05:00
{
2011-04-14 17:44:22 -05:00
char * vdata , * vdatap = NULL ;
2010-06-30 20:41:21 -05:00
char * end , * check_a , * check_b ;
switch_event_t * e = * event ;
char * var_array [ 1024 ] = { 0 } ;
int var_count = 0 ;
2012-04-11 15:30:37 -05:00
char * next = NULL , * vnext = NULL ;
2011-04-14 17:44:22 -05:00
if ( dup ) {
vdatap = strdup ( data ) ;
vdata = vdatap ;
} else {
vdata = data ;
}
2010-06-30 20:41:21 -05:00
end = switch_find_end_paren ( vdata , a , b ) ;
check_a = end ;
2010-07-01 14:21:44 -05:00
while ( check_a & & ( check_b = switch_strchr_strict ( check_a , a , " " ) ) ) {
2010-06-30 20:41:21 -05:00
if ( ( check_b = switch_find_end_paren ( check_b , a , b ) ) ) {
check_a = check_b ;
}
}
if ( check_a ) end = check_a ;
if ( end ) {
2012-04-11 15:30:37 -05:00
next = end ;
2010-06-30 20:41:21 -05:00
vdata + + ;
* end + + = ' \0 ' ;
} else {
2011-04-14 17:44:22 -05:00
if ( dup ) {
free ( vdatap ) ;
}
2010-06-30 20:41:21 -05:00
return SWITCH_STATUS_FALSE ;
}
if ( ! e ) {
switch_event_create_plain ( & e , SWITCH_EVENT_CHANNEL_DATA ) ;
}
for ( ; ; ) {
2012-04-11 15:30:37 -05:00
if ( next ) {
2010-06-30 20:41:21 -05:00
char * pnext ;
2012-04-11 15:30:37 -05:00
2010-06-30 20:41:21 -05:00
* next + + = ' \0 ' ;
2010-07-01 14:21:44 -05:00
if ( ( pnext = switch_strchr_strict ( next , a , " " ) ) ) {
2010-06-30 20:41:21 -05:00
next = pnext + 1 ;
}
2012-04-11 15:30:37 -05:00
vnext = switch_find_end_paren ( next , a , b ) ;
next = NULL ;
2010-06-30 20:41:21 -05:00
}
2011-04-14 17:44:22 -05:00
if ( vdata ) {
if ( * vdata = = ' ^ ' & & * ( vdata + 1 ) = = ' ^ ' ) {
vdata + = 2 ;
c = * vdata + + ;
}
}
2010-06-30 20:41:21 -05:00
if ( ( var_count = switch_separate_string ( vdata , c , var_array , ( sizeof ( var_array ) / sizeof ( var_array [ 0 ] ) ) ) ) ) {
int x = 0 ;
for ( x = 0 ; x < var_count ; x + + ) {
char * inner_var_array [ 2 ] = { 0 } ;
int inner_var_count ;
if ( ( inner_var_count = switch_separate_string ( var_array [ x ] , ' = ' ,
inner_var_array , ( sizeof ( inner_var_array ) / sizeof ( inner_var_array [ 0 ] ) ) ) ) = = 2 ) {
2012-04-12 09:53:53 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Parsing variable [%s]=[%s] \n " , inner_var_array [ 0 ] , inner_var_array [ 1 ] ) ;
2010-06-30 20:41:21 -05:00
switch_event_add_header_string ( e , SWITCH_STACK_BOTTOM , inner_var_array [ 0 ] , inner_var_array [ 1 ] ) ;
}
}
}
2012-04-11 15:30:37 -05:00
if ( vnext ) {
vdata = vnext ;
2010-06-30 20:41:21 -05:00
} else {
break ;
}
}
* event = e ;
2011-04-14 17:44:22 -05:00
if ( dup ) {
* new_data = strdup ( end ) ;
free ( vdatap ) ;
} else {
* new_data = end ;
}
2010-06-30 20:41:21 -05:00
return SWITCH_STATUS_SUCCESS ;
}
2010-06-17 11:43:09 -05:00
SWITCH_DECLARE ( switch_status_t ) switch_event_create_json ( switch_event_t * * event , const char * json )
{
switch_event_t * new_event ;
cJSON * cj , * cjp ;
if ( ! ( cj = cJSON_Parse ( json ) ) ) {
return SWITCH_STATUS_FALSE ;
}
if ( switch_event_create ( & new_event , SWITCH_EVENT_CLONE ) ! = SWITCH_STATUS_SUCCESS ) {
cJSON_Delete ( cj ) ;
return SWITCH_STATUS_FALSE ;
}
for ( cjp = cj - > child ; cjp ; cjp = cjp - > next ) {
char * name = cjp - > string ;
char * value = cjp - > valuestring ;
2011-05-25 15:42:36 -05:00
2010-06-17 11:43:09 -05:00
if ( name & & value ) {
if ( ! strcasecmp ( name , " _body " ) ) {
2010-06-17 12:01:35 -05:00
switch_event_add_body ( new_event , value , SWITCH_VA_NONE ) ;
2010-06-17 11:43:09 -05:00
} else {
if ( ! strcasecmp ( name , " event-name " ) ) {
switch_event_del_header ( new_event , " event-name " ) ;
2011-05-25 15:42:36 -05:00
switch_name_event ( value , & new_event - > event_id ) ;
2010-06-17 11:43:09 -05:00
}
2011-05-25 15:42:36 -05:00
2010-06-17 11:43:09 -05:00
switch_event_add_header_string ( new_event , SWITCH_STACK_BOTTOM , name , value ) ;
}
2011-05-25 15:42:36 -05:00
} else if ( name ) {
if ( cjp - > type = = cJSON_Array ) {
int i , x = cJSON_GetArraySize ( cjp ) ;
for ( i = 0 ; i < x ; i + + ) {
cJSON * item = cJSON_GetArrayItem ( cjp , i ) ;
if ( item & & item - > type = = cJSON_String & & item - > valuestring ) {
switch_event_add_header_string ( new_event , SWITCH_STACK_PUSH , name , item - > valuestring ) ;
}
}
}
2010-06-17 11:43:09 -05:00
}
}
cJSON_Delete ( cj ) ;
* event = new_event ;
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_DECLARE ( switch_status_t ) switch_event_serialize_json ( switch_event_t * event , char * * str )
{
switch_event_header_t * hp ;
cJSON * cj ;
* str = NULL ;
cj = cJSON_CreateObject ( ) ;
for ( hp = event - > headers ; hp ; hp = hp - > next ) {
2011-05-25 15:42:36 -05:00
if ( hp - > idx ) {
cJSON * a = cJSON_CreateArray ( ) ;
int i ;
for ( i = 0 ; i < hp - > idx ; i + + ) {
cJSON_AddItemToArray ( a , cJSON_CreateString ( hp - > array [ i ] ) ) ;
}
cJSON_AddItemToObject ( cj , hp - > name , a ) ;
} else {
cJSON_AddItemToObject ( cj , hp - > name , cJSON_CreateString ( hp - > value ) ) ;
}
}
2010-06-17 11:43:09 -05:00
if ( event - > body ) {
int blen = ( int ) strlen ( event - > body ) ;
char tmp [ 25 ] ;
switch_snprintf ( tmp , sizeof ( tmp ) , " %d " , blen ) ;
cJSON_AddItemToObject ( cj , " Content-Length " , cJSON_CreateString ( tmp ) ) ;
cJSON_AddItemToObject ( cj , " _body " , cJSON_CreateString ( event - > body ) ) ;
}
* str = cJSON_Print ( cj ) ;
cJSON_Delete ( cj ) ;
return SWITCH_STATUS_SUCCESS ;
}
2006-05-10 19:07:38 +00:00
static switch_xml_t add_xml_header ( switch_xml_t xml , char * name , char * value , int offset )
{
2008-12-31 22:44:23 +00:00
switch_xml_t header = switch_xml_add_child_d ( xml , name , offset ) ;
2010-02-06 03:38:24 +00:00
2008-01-29 19:01:35 +00:00
if ( header ) {
2009-02-13 19:03:34 +00:00
switch_size_t encode_len = ( strlen ( value ) * 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 * ) value , encode_buf , encode_len ) ;
switch_xml_set_txt_d ( header , encode_buf ) ;
free ( encode_buf ) ;
2006-05-10 19:07:38 +00:00
}
2010-02-06 03:38:24 +00:00
2006-05-10 19:07:38 +00:00
return header ;
}
2010-02-06 03:38:24 +00:00
SWITCH_DECLARE ( switch_xml_t ) switch_event_xmlize ( switch_event_t * event , const char * fmt , . . . )
2006-05-10 19:07:38 +00:00
{
switch_event_header_t * hp ;
char * data = NULL , * body = NULL ;
int ret = 0 ;
switch_xml_t xml = NULL ;
uint32_t off = 0 ;
va_list ap ;
2008-12-31 22:44:23 +00:00
switch_xml_t xheaders = NULL ;
2006-05-10 19:07:38 +00:00
if ( ! ( xml = switch_xml_new ( " event " ) ) ) {
return xml ;
}
2010-08-14 16:49:20 -04:00
if ( ! zstr ( fmt ) ) {
2006-05-10 19:07:38 +00:00
va_start ( ap , fmt ) ;
# ifdef HAVE_VASPRINTF
ret = vasprintf ( & data , fmt , ap ) ;
# else
data = ( char * ) malloc ( 2048 ) ;
2008-05-27 04:30:03 +00:00
if ( ! data )
return NULL ;
2006-10-16 19:56:42 +00:00
ret = vsnprintf ( data , 2048 , fmt , ap ) ;
2006-05-10 19:07:38 +00:00
# endif
va_end ( ap ) ;
if ( ret = = - 1 ) {
2008-05-16 17:25:43 +00:00
# ifndef HAVE_VASPRINTF
free ( data ) ;
# endif
2006-05-10 19:07:38 +00:00
return NULL ;
}
}
2008-12-31 22:44:23 +00:00
if ( ( xheaders = switch_xml_add_child_d ( xml , " headers " , off + + ) ) ) {
int hoff = 0 ;
for ( hp = event - > headers ; hp ; hp = hp - > next ) {
2011-05-25 15:42:36 -05:00
if ( hp - > idx ) {
int i ;
for ( i = 0 ; i < hp - > idx ; i + + ) {
add_xml_header ( xheaders , hp - > name , hp - > array [ i ] , hoff + + ) ;
}
} else {
add_xml_header ( xheaders , hp - > name , hp - > value , hoff + + ) ;
}
2008-12-31 22:44:23 +00:00
}
2006-05-10 19:07:38 +00:00
}
2009-10-23 16:03:42 +00:00
if ( ! zstr ( data ) ) {
2006-05-10 19:07:38 +00:00
body = data ;
} else if ( event - > body ) {
body = event - > body ;
}
if ( body ) {
int blen = ( int ) strlen ( body ) ;
char blena [ 25 ] ;
2007-12-12 21:53:32 +00:00
switch_snprintf ( blena , sizeof ( blena ) , " %d " , blen ) ;
2006-05-10 19:07:38 +00:00
if ( blen ) {
switch_xml_t xbody = NULL ;
add_xml_header ( xml , " Content-Length " , blena , off + + ) ;
2006-08-18 01:28:50 +00:00
if ( ( xbody = switch_xml_add_child_d ( xml , " body " , off + + ) ) ) {
2006-05-10 19:07:38 +00:00
switch_xml_set_txt_d ( xbody , body ) ;
}
}
}
2007-03-29 22:31:56 +00:00
2006-05-10 19:07:38 +00:00
if ( data ) {
free ( data ) ;
}
return xml ;
}
2009-02-21 23:19:58 +00:00
SWITCH_DECLARE ( void ) switch_event_prep_for_delivery_detailed ( const char * file , const char * func , int line , switch_event_t * event )
2005-12-19 18:55:31 +00:00
{
2005-12-21 22:25:22 +00:00
switch_time_exp_t tm ;
char date [ 80 ] = " " ;
2006-03-30 23:02:50 +00:00
switch_size_t retsize ;
2009-01-25 21:23:07 +00:00
switch_time_t ts = switch_micro_time_now ( ) ;
2005-12-19 18:55:31 +00:00
2012-02-07 11:25:23 -06:00
switch_mutex_lock ( EVENT_QUEUE_MUTEX ) ;
EVENT_SEQUENCE_NR + + ;
switch_mutex_unlock ( EVENT_QUEUE_MUTEX ) ;
2009-02-21 23:19:58 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Event-Name " , switch_event_name ( event - > event_id ) ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Core-UUID " , switch_core_get_uuid ( ) ) ;
2011-04-29 10:24:50 -05:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " FreeSWITCH-Hostname " , switch_core_get_hostname ( ) ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " FreeSWITCH-Switchname " , switch_core_get_switchname ( ) ) ;
2009-02-21 23:19:58 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " FreeSWITCH-IPv4 " , guess_ip_v4 ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " FreeSWITCH-IPv6 " , guess_ip_v6 ) ;
switch_time_exp_lt ( & tm , ts ) ;
switch_strftime_nocheck ( date , & retsize , sizeof ( date ) , " %Y-%m-%d %T " , & tm ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Event-Date-Local " , date ) ;
switch_rfc822_date ( date , ts ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Event-Date-GMT " , date ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Event-Date-Timestamp " , " % " SWITCH_UINT64_T_FMT , ( uint64_t ) ts ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Event-Calling-File " , switch_cut_path ( file ) ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Event-Calling-Function " , func ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Event-Calling-Line-Number " , " %d " , line ) ;
2012-02-07 11:25:23 -06:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " Event-Sequence " , " % " SWITCH_UINT64_T_FMT , ( uint64_t ) EVENT_SEQUENCE_NR ) ;
2009-02-21 23:19:58 +00:00
}
SWITCH_DECLARE ( switch_status_t ) switch_event_fire_detailed ( const char * file , const char * func , int line , switch_event_t * * event , void * user_data )
{
2007-12-11 19:23:57 +00:00
switch_assert ( BLOCK ! = NULL ) ;
switch_assert ( RUNTIME_POOL ! = NULL ) ;
switch_assert ( EVENT_QUEUE_MUTEX ! = NULL ) ;
switch_assert ( RUNTIME_POOL ! = NULL ) ;
2006-01-03 01:17:59 +00:00
2008-03-14 16:21:13 +00:00
if ( SYSTEM_RUNNING < = 0 ) {
2005-12-22 18:53:33 +00:00
/* sorry we're closed */
switch_event_destroy ( event ) ;
2009-02-20 01:10:59 +00:00
return SWITCH_STATUS_SUCCESS ;
2005-12-22 18:53:33 +00:00
}
2005-12-19 18:55:31 +00:00
2005-12-21 16:24:37 +00:00
if ( user_data ) {
( * event ) - > event_user_data = user_data ;
}
2008-05-27 04:30:03 +00:00
2012-05-03 16:31:21 -05:00
if ( ! EVENT_QUEUE_THREADS [ ( * event ) - > priority ] & & ( * event ) - > priority < 3 ) {
switch_threadattr_t * thd_attr ;
switch_queue_create ( & EVENT_QUEUE [ ( * event ) - > priority ] , POOL_COUNT_MAX + 10 , THRUNTIME_POOL ) ;
switch_threadattr_create ( & thd_attr , THRUNTIME_POOL ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
switch_threadattr_priority_increase ( thd_attr ) ;
switch_thread_create ( & EVENT_QUEUE_THREADS [ ( * event ) - > priority ] , thd_attr , switch_event_thread , EVENT_QUEUE [ ( * event ) - > priority ] , RUNTIME_POOL ) ;
}
2009-03-30 21:09:49 +00:00
for ( ; ; ) {
2012-05-03 16:31:21 -05:00
if ( switch_queue_trypush ( EVENT_QUEUE [ ( * event ) - > priority ] , * event ) = = SWITCH_STATUS_SUCCESS ) {
goto end ;
2009-03-30 21:09:49 +00:00
}
2010-02-06 03:38:24 +00:00
2012-05-03 16:31:21 -05:00
2009-03-30 21:09:49 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Event queue is full! \n " ) ;
switch_yield ( 100000 ) ;
}
2010-02-06 03:38:24 +00:00
end :
2007-03-29 22:31:56 +00:00
2005-12-19 18:55:31 +00:00
* event = NULL ;
2005-12-13 20:52:33 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2010-02-06 03:38:24 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_bind_removable ( const char * id , switch_event_types_t event , const char * subclass_name ,
2008-07-01 23:41:09 +00:00
switch_event_callback_t callback , void * user_data , switch_event_node_t * * node )
2005-12-13 20:52:33 +00:00
{
2006-04-29 06:05:03 +00:00
switch_event_node_t * event_node ;
switch_event_subclass_t * subclass = NULL ;
2005-12-13 20:52:33 +00:00
2007-12-11 19:23:57 +00:00
switch_assert ( BLOCK ! = NULL ) ;
switch_assert ( RUNTIME_POOL ! = NULL ) ;
2005-12-13 20:52:33 +00:00
2008-07-01 23:41:09 +00:00
if ( node ) {
* node = NULL ;
}
2010-05-10 13:06:22 -05:00
2005-12-15 19:10:43 +00:00
if ( subclass_name ) {
2008-07-01 23:41:09 +00:00
if ( ! ( subclass = switch_core_hash_find ( CUSTOM_HASH , subclass_name ) ) ) {
switch_event_reserve_subclass_detailed ( id , subclass_name ) ;
subclass = switch_core_hash_find ( CUSTOM_HASH , subclass_name ) ;
2009-12-04 20:28:55 +00:00
subclass - > bind = 1 ;
2008-07-01 23:41:09 +00:00
}
if ( ! subclass ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Could not reserve subclass. '%s' \n " , subclass_name ) ;
return SWITCH_STATUS_FALSE ;
2005-12-15 19:10:43 +00:00
}
}
2010-02-06 03:38:24 +00:00
2008-07-01 23:41:09 +00:00
if ( event < = SWITCH_EVENT_ALL ) {
switch_zmalloc ( event_node , sizeof ( * event_node ) ) ;
switch_thread_rwlock_wrlock ( RWLOCK ) ;
2011-11-28 08:27:40 -06:00
switch_mutex_lock ( BLOCK ) ;
2006-01-20 15:05:05 +00:00
/* <LOCKED> ----------------------------------------------- */
2008-07-01 23:41:09 +00:00
event_node - > id = DUP ( id ) ;
2005-12-19 18:55:31 +00:00
event_node - > event_id = event ;
2011-08-10 07:55:17 -05:00
if ( subclass_name ) {
event_node - > subclass_name = DUP ( subclass_name ) ;
}
2005-12-13 20:52:33 +00:00
event_node - > callback = callback ;
2005-12-15 19:10:43 +00:00
event_node - > user_data = user_data ;
2005-12-13 20:52:33 +00:00
if ( EVENT_NODES [ event ] ) {
event_node - > next = EVENT_NODES [ event ] ;
}
2005-12-15 19:10:43 +00:00
2005-12-13 20:52:33 +00:00
EVENT_NODES [ event ] = event_node ;
2005-12-14 21:29:46 +00:00
switch_mutex_unlock ( BLOCK ) ;
2011-11-28 08:27:40 -06:00
switch_thread_rwlock_unlock ( RWLOCK ) ;
2006-01-20 15:05:05 +00:00
/* </LOCKED> ----------------------------------------------- */
2008-07-01 23:41:09 +00:00
if ( node ) {
* node = event_node ;
}
2005-12-13 20:52:33 +00:00
return SWITCH_STATUS_SUCCESS ;
}
return SWITCH_STATUS_MEMERR ;
}
2006-11-27 22:30:48 +00:00
2008-07-01 23:41:09 +00:00
2010-02-06 03:38:24 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_bind ( const char * id , switch_event_types_t event , const char * subclass_name ,
switch_event_callback_t callback , void * user_data )
2008-07-01 23:41:09 +00:00
{
return switch_event_bind_removable ( id , event , subclass_name , callback , user_data , NULL ) ;
}
2008-07-22 22:23:50 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_unbind_callback ( switch_event_callback_t callback )
{
switch_event_node_t * n , * np , * lnp = NULL ;
switch_status_t status = SWITCH_STATUS_FALSE ;
int id ;
switch_thread_rwlock_wrlock ( RWLOCK ) ;
switch_mutex_lock ( BLOCK ) ;
/* <LOCKED> ----------------------------------------------- */
2009-12-04 20:28:55 +00:00
for ( id = 0 ; id < = SWITCH_EVENT_ALL ; id + + ) {
2008-07-22 22:23:50 +00:00
lnp = NULL ;
for ( np = EVENT_NODES [ id ] ; np ; ) {
n = np ;
np = np - > next ;
if ( n - > callback = = callback ) {
if ( lnp ) {
lnp - > next = n - > next ;
} else {
EVENT_NODES [ n - > event_id ] = n - > next ;
}
2009-12-04 20:28:55 +00:00
2008-07-22 22:23:50 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Event Binding deleted for %s:%s \n " , n - > id , switch_event_name ( n - > event_id ) ) ;
2011-08-10 07:55:17 -05:00
FREE ( n - > subclass_name ) ;
2008-07-22 22:23:50 +00:00
FREE ( n - > id ) ;
FREE ( n ) ;
status = SWITCH_STATUS_SUCCESS ;
} else {
lnp = n ;
}
}
}
switch_mutex_unlock ( BLOCK ) ;
switch_thread_rwlock_unlock ( RWLOCK ) ;
/* </LOCKED> ----------------------------------------------- */
return status ;
}
2008-07-01 23:41:09 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_unbind ( switch_event_node_t * * node )
{
switch_event_node_t * n , * np , * lnp = NULL ;
switch_status_t status = SWITCH_STATUS_FALSE ;
n = * node ;
2008-07-07 15:04:35 +00:00
if ( ! n ) {
return status ;
}
2008-07-01 23:41:09 +00:00
switch_thread_rwlock_wrlock ( RWLOCK ) ;
switch_mutex_lock ( BLOCK ) ;
/* <LOCKED> ----------------------------------------------- */
for ( np = EVENT_NODES [ n - > event_id ] ; np ; np = np - > next ) {
if ( np = = n ) {
if ( lnp ) {
lnp - > next = n - > next ;
} else {
EVENT_NODES [ n - > event_id ] = n - > next ;
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Event Binding deleted for %s:%s \n " , n - > id , switch_event_name ( n - > event_id ) ) ;
2011-08-10 07:55:17 -05:00
FREE ( n - > subclass_name ) ;
2008-07-01 23:41:09 +00:00
FREE ( n - > id ) ;
FREE ( n ) ;
* node = NULL ;
status = SWITCH_STATUS_SUCCESS ;
break ;
}
lnp = np ;
}
switch_mutex_unlock ( BLOCK ) ;
switch_thread_rwlock_unlock ( RWLOCK ) ;
/* </LOCKED> ----------------------------------------------- */
return status ;
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_event_create_pres_in_detailed ( char * file , char * func , int line ,
2008-01-03 01:21:26 +00:00
const char * proto , const char * login ,
const char * from , const char * from_domain ,
2008-05-27 04:30:03 +00:00
const char * status , const char * event_type ,
2008-01-03 01:21:26 +00:00
const char * alt_event_type , int event_count ,
const char * unique_id , const char * channel_state ,
const char * answer_state , const char * call_direction )
{
2008-05-27 04:30:03 +00:00
switch_event_t * pres_event ;
2008-01-03 01:21:26 +00:00
if ( switch_event_create_subclass ( & pres_event , SWITCH_EVENT_PRESENCE_IN , SWITCH_EVENT_SUBCLASS_ANY ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( pres_event , SWITCH_STACK_TOP , " proto " , proto ) ;
switch_event_add_header_string ( pres_event , SWITCH_STACK_TOP , " login " , login ) ;
switch_event_add_header ( pres_event , SWITCH_STACK_TOP , " from " , " %s@%s " , from , from_domain ) ;
switch_event_add_header_string ( pres_event , SWITCH_STACK_TOP , " status " , status ) ;
switch_event_add_header_string ( pres_event , SWITCH_STACK_TOP , " event_type " , event_type ) ;
switch_event_add_header_string ( pres_event , SWITCH_STACK_TOP , " alt_event_type " , alt_event_type ) ;
switch_event_add_header ( pres_event , SWITCH_STACK_TOP , " event_count " , " %d " , event_count ) ;
switch_event_add_header_string ( pres_event , SWITCH_STACK_TOP , " unique-id " , alt_event_type ) ;
switch_event_add_header_string ( pres_event , SWITCH_STACK_TOP , " channel-state " , channel_state ) ;
switch_event_add_header_string ( pres_event , SWITCH_STACK_TOP , " answer-state " , answer_state ) ;
2009-02-23 16:31:59 +00:00
switch_event_add_header_string ( pres_event , SWITCH_STACK_TOP , " presence-call-direction " , call_direction ) ;
2008-01-03 01:21:26 +00:00
switch_event_fire_detailed ( file , func , line , & pres_event , NULL ) ;
return SWITCH_STATUS_SUCCESS ;
}
return SWITCH_STATUS_MEMERR ;
}
2008-01-21 18:17:12 +00:00
# define resize(l) {\
char * dp ; \
olen + = ( len + l + block ) ; \
cpos = c - data ; \
if ( ( dp = realloc ( data , olen ) ) ) { \
data = dp ; \
c = data + cpos ; \
memset ( c , 0 , olen - cpos ) ; \
} } \
2012-04-12 07:23:08 -05:00
SWITCH_DECLARE ( char * ) switch_event_expand_headers_check ( switch_event_t * event , const char * in , switch_event_t * var_list , switch_event_t * api_list , uint32_t recur )
2008-01-21 18:17:12 +00:00
{
char * p , * c = NULL ;
2008-08-11 15:37:50 +00:00
char * data , * indup , * endof_indup ;
2008-01-21 18:17:12 +00:00
size_t sp = 0 , len = 0 , olen = 0 , vtype = 0 , br = 0 , cpos , block = 128 ;
2009-01-21 21:34:31 +00:00
const char * sub_val = NULL ;
2012-04-11 15:30:37 -05:00
char * cloned_sub_val = NULL , * expanded_sub_val = NULL ;
2008-01-21 18:17:12 +00:00
char * func_val = NULL ;
int nv = 0 ;
2011-03-29 19:55:28 -05:00
char * gvar = NULL , * sb = NULL ;
2008-01-21 18:17:12 +00:00
2012-04-12 07:23:08 -05:00
if ( recur > 100 ) {
return ( char * ) in ;
}
2011-03-28 09:49:48 -05:00
if ( zstr ( in ) ) {
return ( char * ) in ;
}
2009-04-14 15:24:30 +00:00
nv = switch_string_var_check_const ( in ) | | switch_string_has_escaped_data ( in ) ;
2008-05-27 04:30:03 +00:00
2008-01-21 18:17:12 +00:00
if ( ! nv ) {
2008-05-27 04:30:03 +00:00
return ( char * ) in ;
2008-01-21 18:17:12 +00:00
}
nv = 0 ;
olen = strlen ( in ) + 1 ;
indup = strdup ( in ) ;
2008-08-11 20:43:19 +00:00
endof_indup = end_of_p ( indup ) + 1 ;
2008-01-21 18:17:12 +00:00
if ( ( data = malloc ( olen ) ) ) {
memset ( data , 0 , olen ) ;
c = data ;
2008-08-11 15:37:50 +00:00
for ( p = indup ; p & & p < endof_indup & & * p ; p + + ) {
2008-01-21 18:17:12 +00:00
vtype = 0 ;
2008-05-27 04:30:03 +00:00
2008-01-21 18:17:12 +00:00
if ( * p = = ' \\ ' ) {
if ( * ( p + 1 ) = = ' $ ' ) {
nv = 1 ;
2009-05-21 20:10:24 +00:00
p + + ;
2010-03-03 18:31:19 +00:00
} else if ( * ( p + 1 ) = = ' \' ' ) {
p + + ;
continue ;
2008-01-21 18:17:12 +00:00
} else if ( * ( p + 1 ) = = ' \\ ' ) {
* c + + = * p + + ;
len + + ;
continue ;
}
}
if ( * p = = ' $ ' & & ! nv ) {
2008-05-27 04:30:03 +00:00
if ( * ( p + 1 ) ) {
if ( * ( p + 1 ) = = ' { ' ) {
2008-01-21 18:17:12 +00:00
vtype = 1 ;
} else {
nv = 1 ;
}
} else {
nv = 1 ;
}
}
if ( nv ) {
* c + + = * p ;
len + + ;
nv = 0 ;
continue ;
}
if ( vtype ) {
char * s = p , * e , * vname , * vval = NULL ;
size_t nlen ;
s + + ;
if ( vtype = = 1 & & * s = = ' { ' ) {
br = 1 ;
s + + ;
}
e = s ;
vname = s ;
while ( * e ) {
if ( br = = 1 & & * e = = ' } ' ) {
br = 0 ;
* e + + = ' \0 ' ;
break ;
}
if ( br > 0 ) {
if ( e ! = s & & * e = = ' { ' ) {
br + + ;
} else if ( br > 1 & & * e = = ' } ' ) {
br - - ;
}
}
2008-05-27 04:30:03 +00:00
2008-01-21 18:17:12 +00:00
e + + ;
}
2008-08-11 15:37:50 +00:00
p = e > endof_indup ? endof_indup : e ;
2008-05-27 04:30:03 +00:00
2011-03-29 19:55:28 -05:00
vval = NULL ;
for ( sb = vname ; sb & & * sb ; sb + + ) {
if ( * sb = = ' ' ) {
vval = sb ;
break ;
} else if ( * sb = = ' ( ' ) {
vval = sb ;
br = 1 ;
break ;
}
}
if ( vval ) {
2008-01-21 18:17:12 +00:00
e = vval - 1 ;
* vval + + = ' \0 ' ;
2011-03-29 19:55:28 -05:00
2008-05-27 04:30:03 +00:00
while ( * e = = ' ' ) {
2008-01-21 18:17:12 +00:00
* e - - = ' \0 ' ;
}
e = vval ;
2010-10-08 15:59:22 -05:00
2008-05-27 04:30:03 +00:00
while ( e & & * e ) {
2008-01-21 18:17:12 +00:00
if ( * e = = ' ( ' ) {
br + + ;
} else if ( br > 1 & & * e = = ' ) ' ) {
br - - ;
} else if ( br = = 1 & & * e = = ' ) ' ) {
* e = ' \0 ' ;
break ;
}
e + + ;
}
vtype = 2 ;
}
if ( vtype = = 1 ) {
char * expanded = NULL ;
int offset = 0 ;
int ooffset = 0 ;
char * ptr ;
2011-05-25 15:42:36 -05:00
int idx = - 1 ;
2012-04-12 07:23:08 -05:00
if ( ( expanded = switch_event_expand_headers_check ( event , ( char * ) vname , var_list , api_list , recur + 1 ) ) = = vname ) {
2008-01-21 18:17:12 +00:00
expanded = NULL ;
} else {
vname = expanded ;
}
if ( ( ptr = strchr ( vname , ' : ' ) ) ) {
* ptr + + = ' \0 ' ;
offset = atoi ( ptr ) ;
if ( ( ptr = strchr ( ptr , ' : ' ) ) ) {
ptr + + ;
ooffset = atoi ( ptr ) ;
}
}
2008-05-27 04:30:03 +00:00
2011-05-25 15:42:36 -05:00
if ( ( ptr = strchr ( vname , ' [ ' ) ) & & strchr ( ptr , ' ] ' ) ) {
* ptr + + = ' \0 ' ;
idx = atoi ( ptr ) ;
}
if ( ! ( sub_val = switch_event_get_header_idx ( event , vname , idx ) ) ) {
2011-02-03 11:19:24 -06:00
switch_safe_free ( gvar ) ;
2011-02-02 15:43:26 -06:00
if ( ( gvar = switch_core_get_variable_dup ( vname ) ) ) {
sub_val = gvar ;
}
2012-01-09 12:47:47 -06:00
if ( var_list & & ! switch_event_check_permission_list ( var_list , vname ) ) {
sub_val = " INVALID " ;
}
2008-01-21 18:17:12 +00:00
2012-04-12 07:23:08 -05:00
if ( ( expanded_sub_val = switch_event_expand_headers_check ( event , sub_val , var_list , api_list , recur + 1 ) ) = = sub_val ) {
2012-04-11 15:30:37 -05:00
expanded_sub_val = NULL ;
} else {
sub_val = expanded_sub_val ;
}
2012-04-18 19:00:37 -05:00
}
2008-01-21 18:17:12 +00:00
2012-04-18 19:00:37 -05:00
if ( offset | | ooffset ) {
cloned_sub_val = strdup ( sub_val ) ;
switch_assert ( cloned_sub_val ) ;
sub_val = cloned_sub_val ;
}
2012-04-11 15:30:37 -05:00
2012-04-18 19:00:37 -05:00
if ( offset > = 0 ) {
sub_val + = offset ;
} else if ( ( size_t ) abs ( offset ) < = strlen ( sub_val ) ) {
sub_val = cloned_sub_val + ( strlen ( cloned_sub_val ) + offset ) ;
}
2008-01-21 18:17:12 +00:00
2012-04-18 19:00:37 -05:00
if ( ooffset > 0 & & ( size_t ) ooffset < strlen ( sub_val ) ) {
if ( ( ptr = ( char * ) sub_val + ooffset ) ) {
* ptr = ' \0 ' ;
2008-01-21 18:17:12 +00:00
}
}
2012-04-18 19:02:06 -05:00
2008-01-21 18:17:12 +00:00
switch_safe_free ( expanded ) ;
} else {
switch_stream_handle_t stream = { 0 } ;
char * expanded = NULL ;
SWITCH_STANDARD_STREAM ( stream ) ;
if ( stream . data ) {
char * expanded_vname = NULL ;
2012-04-12 07:23:08 -05:00
if ( ( expanded_vname = switch_event_expand_headers_check ( event , ( char * ) vname , var_list , api_list , recur + 1 ) ) = = vname ) {
2008-01-21 18:17:12 +00:00
expanded_vname = NULL ;
} else {
vname = expanded_vname ;
}
2012-04-12 07:23:08 -05:00
if ( ( expanded = switch_event_expand_headers_check ( event , vval , var_list , api_list , recur + 1 ) ) = = vval ) {
2008-01-21 18:17:12 +00:00
expanded = NULL ;
} else {
vval = expanded ;
}
2012-01-09 12:47:47 -06:00
if ( api_list & & ! switch_event_check_permission_list ( api_list , vname ) ) {
func_val = " INVALID " ;
sub_val = " INVALID " ;
2008-01-21 18:17:12 +00:00
} else {
2012-01-09 12:47:47 -06:00
if ( switch_api_execute ( vname , vval , NULL , & stream ) = = SWITCH_STATUS_SUCCESS ) {
func_val = stream . data ;
sub_val = func_val ;
} else {
free ( stream . data ) ;
}
2008-01-21 18:17:12 +00:00
}
2008-05-27 04:30:03 +00:00
2008-01-21 18:17:12 +00:00
switch_safe_free ( expanded ) ;
switch_safe_free ( expanded_vname ) ;
2008-05-27 04:30:03 +00:00
2008-01-21 18:17:12 +00:00
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Memory Error! \n " ) ;
free ( data ) ;
free ( indup ) ;
2008-05-27 04:30:03 +00:00
return ( char * ) in ;
2008-01-21 18:17:12 +00:00
}
}
if ( ( nlen = sub_val ? strlen ( sub_val ) : 0 ) ) {
if ( len + nlen > = olen ) {
resize ( nlen ) ;
}
len + = nlen ;
strcat ( c , sub_val ) ;
c + = nlen ;
}
switch_safe_free ( func_val ) ;
switch_safe_free ( cloned_sub_val ) ;
2012-04-11 15:30:37 -05:00
switch_safe_free ( expanded_sub_val ) ;
2008-01-21 18:17:12 +00:00
sub_val = NULL ;
vname = NULL ;
vtype = 0 ;
br = 0 ;
}
if ( len + 1 > = olen ) {
resize ( 1 ) ;
}
if ( sp ) {
* c + + = ' ' ;
sp = 0 ;
len + + ;
}
if ( * p = = ' $ ' ) {
p - - ;
} else {
* c + + = * p ;
len + + ;
}
}
}
free ( indup ) ;
2011-02-03 11:19:24 -06:00
switch_safe_free ( gvar ) ;
2008-05-27 04:30:03 +00:00
2008-01-21 18:17:12 +00:00
return data ;
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( char * ) switch_event_build_param_string ( switch_event_t * event , const char * prefix , switch_hash_t * vars_map )
2008-01-23 20:59:25 +00:00
{
switch_stream_handle_t stream = { 0 } ;
switch_size_t encode_len = 1024 , new_len = 0 ;
char * encode_buf = NULL ;
2008-05-27 04:30:03 +00:00
const char * prof [ 12 ] = { 0 } , * prof_names [ 12 ] = {
0 } ;
2008-01-23 20:59:25 +00:00
char * e = NULL ;
switch_event_header_t * hi ;
uint32_t x = 0 ;
2008-05-27 04:30:03 +00:00
void * data = NULL ;
2008-01-23 20:59:25 +00:00
SWITCH_STANDARD_STREAM ( stream ) ;
if ( prefix ) {
stream . write_function ( & stream , " %s& " , prefix ) ;
}
encode_buf = malloc ( encode_len ) ;
switch_assert ( encode_buf ) ;
for ( x = 0 ; prof [ x ] ; x + + ) {
2009-10-23 16:03:42 +00:00
if ( zstr ( prof [ x ] ) ) {
2008-01-23 20:59:25 +00:00
continue ;
}
new_len = ( strlen ( prof [ x ] ) * 3 ) + 1 ;
if ( encode_len < new_len ) {
char * tmp ;
encode_len = new_len ;
if ( ! ( tmp = realloc ( encode_buf , encode_len ) ) ) {
abort ( ) ;
}
encode_buf = tmp ;
}
2008-05-21 21:31:17 +00:00
switch_url_encode ( prof [ x ] , encode_buf , encode_len ) ;
2008-01-23 20:59:25 +00:00
stream . write_function ( & stream , " %s=%s& " , prof_names [ x ] , encode_buf ) ;
}
2008-01-23 21:14:38 +00:00
if ( event ) {
if ( ( hi = event - > headers ) ) {
2008-05-27 04:30:03 +00:00
2008-01-23 21:14:38 +00:00
for ( ; hi ; hi = hi - > next ) {
char * var = hi - > name ;
char * val = hi - > value ;
2008-05-27 04:30:03 +00:00
if ( vars_map ! = NULL ) {
if ( ( data = switch_core_hash_find ( vars_map , var ) ) = = NULL | | strcasecmp ( ( ( char * ) data ) , " enabled " ) )
continue ;
2008-05-15 20:29:08 +00:00
}
2008-05-27 04:30:03 +00:00
2008-01-23 21:14:38 +00:00
new_len = ( strlen ( ( char * ) var ) * 3 ) + 1 ;
if ( encode_len < new_len ) {
char * tmp ;
2008-05-27 04:30:03 +00:00
2008-01-23 21:14:38 +00:00
encode_len = new_len ;
2008-05-27 04:30:03 +00:00
2008-01-23 21:14:38 +00:00
tmp = realloc ( encode_buf , encode_len ) ;
switch_assert ( tmp ) ;
encode_buf = tmp ;
}
2008-01-23 20:59:25 +00:00
2008-05-21 21:31:17 +00:00
switch_url_encode ( ( char * ) val , encode_buf , encode_len ) ;
2008-01-23 21:14:38 +00:00
stream . write_function ( & stream , " %s=%s& " , ( char * ) var , encode_buf ) ;
2008-01-23 20:59:25 +00:00
2008-01-23 21:14:38 +00:00
}
2008-01-23 20:59:25 +00:00
}
}
2008-05-27 04:30:03 +00:00
2008-01-23 20:59:25 +00:00
e = ( char * ) stream . data + ( strlen ( ( char * ) stream . data ) - 1 ) ;
if ( e & & * e = = ' & ' ) {
* e = ' \0 ' ;
}
switch_safe_free ( encode_buf ) ;
return stream . data ;
}
2012-01-09 12:47:47 -06:00
SWITCH_DECLARE ( int ) switch_event_check_permission_list ( switch_event_t * list , const char * name )
{
const char * v ;
int r = 0 ;
2012-01-20 14:52:56 -05:00
int default_allow = 0 ;
if ( ! list ) {
return 1 ;
}
default_allow = switch_test_flag ( list , EF_DEFAULT_ALLOW ) ;
2012-01-09 12:47:47 -06:00
if ( ! list - > headers ) {
return default_allow ;
}
if ( ( v = switch_event_get_header ( list , name ) ) ) {
if ( * v = = ' d ' ) {
r = 0 ;
} else {
r = 1 ;
}
} else {
r = default_allow ;
}
return r ;
}
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 :
2008-07-03 19:12:26 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
2006-11-27 22:30:48 +00:00
*/