@ -174,9 +174,21 @@ static const char *channel_snapshot_get_name(struct stasis_message *message)
*/
static int channel_snapshot_hash_cb ( const void * obj , const int flags )
{
const struct ast_channel_snapshot * snapshot = obj ;
const char * name = ( flags & OBJ_KEY ) ? obj : snapshot - > name ;
return ast_str_case_hash ( name ) ;
const struct ast_channel_snapshot * object = obj ;
const char * key ;
switch ( flags & OBJ_SEARCH_MASK ) {
case OBJ_SEARCH_KEY :
key = obj ;
break ;
case OBJ_SEARCH_OBJECT :
key = object - > name ;
break ;
default :
ast_assert ( 0 ) ;
return 0 ;
}
return ast_str_case_hash ( key ) ;
}
/*!
@ -185,10 +197,28 @@ static int channel_snapshot_hash_cb(const void *obj, const int flags)
*/
static int channel_snapshot_cmp_cb ( void * obj , void * arg , int flags )
{
struct ast_channel_snapshot * left = obj ;
struct ast_channel_snapshot * right = arg ;
const char * match = ( flags & OBJ_KEY ) ? arg : right - > name ;
return strcasecmp ( left - > name , match ) ? 0 : ( CMP_MATCH | CMP_STOP ) ;
const struct ast_channel_snapshot * object_left = obj ;
const struct ast_channel_snapshot * object_right = arg ;
const char * right_key = arg ;
int cmp ;
switch ( flags & OBJ_SEARCH_MASK ) {
case OBJ_SEARCH_OBJECT :
right_key = object_right - > name ;
case OBJ_SEARCH_KEY :
cmp = strcasecmp ( object_left - > name , right_key ) ;
break ;
case OBJ_SEARCH_PARTIAL_KEY :
cmp = strncasecmp ( object_left - > name , right_key , strlen ( right_key ) ) ;
break ;
default :
cmp = 0 ;
break ;
}
if ( cmp ) {
return 0 ;
}
return CMP_MATCH ;
}
static void channel_snapshot_dtor ( void * obj )
@ -297,31 +327,33 @@ static void ast_channel_publish_dial_internal(struct ast_channel *caller,
struct ast_channel * peer , struct ast_channel * forwarded , const char * dialstring ,
const char * dialstatus , const char * forward )
{
RAII_VAR ( struct ast_multi_channel_blob * , payload , NULL , ao2_cleanup ) ;
RAII_VAR ( struct stasis_message * , msg , NULL , ao2_cleanup ) ;
RAII_VAR ( struct ast_json * , blob , NULL , ast_json_unref ) ;
RAII_VAR ( struct ast_channel_snapshot * , caller_snapshot , NULL , ao2_cleanup ) ;
RAII_VAR ( struct ast_channel_snapshot * , peer_snapshot , NULL , ao2_cleanup ) ;
RAII_VAR ( struct ast_channel_snapshot * , forwarded_snapshot , NULL , ao2_cleanup ) ;
struct ast_multi_channel_blob * payload ;
struct stasis_message * msg ;
struct ast_json * blob ;
struct ast_channel_snapshot * peer_snapshot ;
if ( ! ast_channel_dial_type ( ) ) {
return ;
}
ast_assert ( peer ! = NULL ) ;
blob = ast_json_pack ( " {s: s, s: s, s: s} " ,
" dialstatus " , S_OR ( dialstatus , " " ) ,
" forward " , S_OR ( forward , " " ) ,
" dialstring " , S_OR ( dialstring , " " ) ) ;
" dialstatus " , S_OR ( dialstatus , " " ) ,
" forward " , S_OR ( forward , " " ) ,
" dialstring " , S_OR ( dialstring , " " ) ) ;
if ( ! blob ) {
return ;
}
payload = ast_multi_channel_blob_create ( blob ) ;
ast_json_unref ( blob ) ;
if ( ! payload ) {
return ;
}
if ( caller ) {
struct ast_channel_snapshot * caller_snapshot ;
ast_channel_lock ( caller ) ;
if ( ast_strlen_zero ( dialstatus ) ) {
caller_snapshot = ast_channel_snapshot_get_latest ( ast_channel_uniqueid ( caller ) ) ;
@ -330,9 +362,11 @@ static void ast_channel_publish_dial_internal(struct ast_channel *caller,
}
ast_channel_unlock ( caller ) ;
if ( ! caller_snapshot ) {
ao2_ref ( payload , - 1 ) ;
return ;
}
ast_multi_channel_blob_add_channel ( payload , " caller " , caller_snapshot ) ;
ao2_ref ( caller_snapshot , - 1 ) ;
}
ast_channel_lock ( peer ) ;
@ -343,26 +377,32 @@ static void ast_channel_publish_dial_internal(struct ast_channel *caller,
}
ast_channel_unlock ( peer ) ;
if ( ! peer_snapshot ) {
ao2_ref ( payload , - 1 ) ;
return ;
}
ast_multi_channel_blob_add_channel ( payload , " peer " , peer_snapshot ) ;
ao2_ref ( peer_snapshot , - 1 ) ;
if ( forwarded ) {
struct ast_channel_snapshot * forwarded_snapshot ;
ast_channel_lock ( forwarded ) ;
forwarded_snapshot = ast_channel_snapshot_create ( forwarded ) ;
ast_channel_unlock ( forwarded ) ;
if ( ! forwarded_snapshot ) {
ao2_ref ( payload , - 1 ) ;
return ;
}
ast_multi_channel_blob_add_channel ( payload , " forwarded " , forwarded_snapshot ) ;
ao2_ref ( forwarded_snapshot , - 1 ) ;
}
msg = stasis_message_create ( ast_channel_dial_type ( ) , payload ) ;
if ( ! msg ) {
return ;
ao2_ref ( payload , - 1 ) ;
if ( msg ) {
publish_message_for_channel_topics ( msg , caller ) ;
ao2_ref ( msg , - 1 ) ;
}
publish_message_for_channel_topics ( msg , caller ) ;
}
static void remove_dial_masquerade ( struct ast_channel * peer ) ;
@ -456,33 +496,33 @@ struct stasis_message *ast_channel_blob_create_from_cache(const char *channel_id
struct stasis_message_type * type ,
struct ast_json * blob )
{
RAII_VAR ( struct ast_channel_snapshot * , snapshot ,
NULL ,
ao2_cleanup ) ;
struct ast_channel_snapshot * snapshot ;
struct stasis_message * msg ;
if ( ! type ) {
return NULL ;
}
snapshot = ast_channel_snapshot_get_latest ( channel_id ) ;
return create_channel_blob_message ( snapshot , type , blob ) ;
msg = create_channel_blob_message ( snapshot , type , blob ) ;
ao2_cleanup ( snapshot ) ;
return msg ;
}
struct stasis_message * ast_channel_blob_create ( struct ast_channel * chan ,
struct stasis_message_type * type , struct ast_json * blob )
{
RAII_VAR ( struct ast_channel_snapshot * , snapshot , NULL , ao2_cleanup ) ;
struct ast_channel_snapshot * snapshot ;
struct stasis_message * msg ;
if ( ! type ) {
return NULL ;
}
if ( chan ) {
snapshot = ast_channel_snapshot_create ( chan ) ;
}
return create_channel_blob_message ( snapshot , type , blob ) ;
snapshot = chan ? ast_channel_snapshot_create ( chan ) : NULL ;
msg = create_channel_blob_message ( snapshot , type , blob ) ;
ao2_cleanup ( snapshot ) ;
return msg ;
}
/*! \brief A channel snapshot wrapper object used in \ref ast_multi_channel_blob objects */
@ -494,31 +534,37 @@ struct channel_role_snapshot {
/*! \brief A multi channel blob data structure for multi_channel_blob stasis messages */
struct ast_multi_channel_blob {
struct ao2_container * channel_snapshots ; /*!< A container holding the snapshots */
struct ast_json * blob ; /* < A blob of JSON data */
struct ast_json * blob ; /* ! < A blob of JSON data */
} ;
/*!
* \ internal
* \ brief Standard c omparison function for \ ref channel_role_snapshot objects
* \ brief C omparison function for \ ref channel_role_snapshot objects
*/
static int channel_role_single_cmp_cb ( void * obj , void * arg , int flags )
{
struct channel_role_snapshot * left = obj ;
struct channel_role_snapshot * right = arg ;
const char * match = ( flags & OBJ_KEY ) ? arg : right - > role ;
return strcasecmp ( left - > role , match ) ? 0 : ( CMP_MATCH | CMP_STOP ) ;
}
/*!
* \ internal
* \ brief Multi comparison function for \ ref channel_role_snapshot objects
*/
static int channel_role_multi_cmp_cb ( void * obj , void * arg , int flags )
{
struct channel_role_snapshot * left = obj ;
struct channel_role_snapshot * right = arg ;
const char * match = ( flags & OBJ_KEY ) ? arg : right - > role ;
return strcasecmp ( left - > role , match ) ? 0 : ( CMP_MATCH ) ;
static int channel_role_cmp_cb ( void * obj , void * arg , int flags )
{
const struct channel_role_snapshot * object_left = obj ;
const struct channel_role_snapshot * object_right = arg ;
const char * right_key = arg ;
int cmp ;
switch ( flags & OBJ_SEARCH_MASK ) {
case OBJ_SEARCH_OBJECT :
right_key = object_right - > role ;
case OBJ_SEARCH_KEY :
cmp = strcasecmp ( object_left - > role , right_key ) ;
break ;
case OBJ_SEARCH_PARTIAL_KEY :
cmp = strncasecmp ( object_left - > role , right_key , strlen ( right_key ) ) ;
break ;
default :
cmp = 0 ;
break ;
}
if ( cmp ) {
return 0 ;
}
return CMP_MATCH ;
}
/*!
@ -527,9 +573,21 @@ static int channel_role_multi_cmp_cb(void *obj, void *arg, int flags)
*/
static int channel_role_hash_cb ( const void * obj , const int flags )
{
const struct channel_role_snapshot * snapshot = obj ;
const char * name = ( flags & OBJ_KEY ) ? obj : snapshot - > role ;
return ast_str_case_hash ( name ) ;
const struct channel_role_snapshot * object = obj ;
const char * key ;
switch ( flags & OBJ_SEARCH_MASK ) {
case OBJ_SEARCH_KEY :
key = obj ;
break ;
case OBJ_SEARCH_OBJECT :
key = object - > role ;
break ;
default :
ast_assert ( 0 ) ;
return 0 ;
}
return ast_str_case_hash ( key ) ;
}
/*!
@ -546,89 +604,80 @@ static void multi_channel_blob_dtor(void *obj)
struct ast_multi_channel_blob * ast_multi_channel_blob_create ( struct ast_json * blob )
{
RAII_VAR ( struct ast_multi_channel_blob * , obj ,
ao2_alloc ( sizeof ( * obj ) , multi_channel_blob_dtor ) ,
ao2_cleanup ) ;
struct ast_multi_channel_blob * obj ;
ast_assert ( blob ! = NULL ) ;
obj = ao2_alloc ( sizeof ( * obj ) , multi_channel_blob_dtor ) ;
if ( ! obj ) {
return NULL ;
}
obj - > channel_snapshots = ao2_container_alloc ( NUM_MULTI_CHANNEL_BLOB_BUCKETS ,
channel_role_hash_cb , channel_ro le_sing le_cmp_cb) ;
channel_role_hash_cb , channel_ro le_cmp_cb) ;
if ( ! obj - > channel_snapshots ) {
ao2_ref ( obj , - 1 ) ;
return NULL ;
}
obj - > blob = ast_json_ref ( blob ) ;
ao2_ref ( obj , + 1 ) ;
return obj ;
}
struct ast_channel_snapshot * ast_channel_snapshot_get_latest ( const char * uniqueid )
{
RAII_VAR ( struct stasis_message * , message , NULL , ao2_cleanup ) ;
struct stasis_message * message ;
struct ast_channel_snapshot * snapshot ;
ast_assert ( ! ast_strlen_zero ( uniqueid ) ) ;
message = stasis_cache_get ( ast_channel_cache ( ) ,
ast_channel_snapshot_type ( ) ,
uniqueid ) ;
message = stasis_cache_get ( ast_channel_cache ( ) , ast_channel_snapshot_type ( ) ,
uniqueid ) ;
if ( ! message ) {
return NULL ;
}
snapshot = stasis_message_data ( message ) ;
if ( ! snapshot ) {
return NULL ;
}
ao2_ref ( snapshot , + 1 ) ;
snapshot = ao2_bump ( stasis_message_data ( message ) ) ;
ao2_ref ( message , - 1 ) ;
return snapshot ;
}
struct ast_channel_snapshot * ast_channel_snapshot_get_latest_by_name ( const char * name )
{
RAII_VAR ( struct stasis_message * , message , NULL , ao2_cleanup ) ;
struct stasis_message * message ;
struct ast_channel_snapshot * snapshot ;
ast_assert ( ! ast_strlen_zero ( name ) ) ;
message = stasis_cache_get ( ast_channel_cache_by_name ( ) ,
ast_channel_snapshot_type ( ) ,
name ) ;
message = stasis_cache_get ( ast_channel_cache_by_name ( ) , ast_channel_snapshot_type ( ) ,
name ) ;
if ( ! message ) {
return NULL ;
}
snapshot = stasis_message_data ( message ) ;
if ( ! snapshot ) {
return NULL ;
}
ao2_ref ( snapshot , + 1 ) ;
snapshot = ao2_bump ( stasis_message_data ( message ) ) ;
ao2_ref ( message , - 1 ) ;
return snapshot ;
}
static void channel_role_snapshot_dtor ( void * obj )
{
struct channel_role_snapshot * role_snapshot = obj ;
ao2_cleanup ( role_snapshot - > snapshot ) ;
}
void ast_multi_channel_blob_add_channel ( struct ast_multi_channel_blob * obj , const char * role , struct ast_channel_snapshot * snapshot )
{
RAII_VAR ( struct channel_role_snapshot * , role_snapshot , NULL , ao2_cleanup ) ;
struct channel_role_snapshot * role_snapshot ;
int role_len = strlen ( role ) + 1 ;
if ( ! obj | | ast_strlen_zero ( role ) | | ! snapshot ) {
return ;
}
role_snapshot = ao2_alloc_options ( sizeof ( * role_snapshot ) + role_len , channel_role_snapshot_dtor ,
AO2_ALLOC_OPT_LOCK_NOLOCK) ;
role_snapshot = ao2_alloc_options ( sizeof ( * role_snapshot ) + role_len ,
channel_role_snapshot_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK) ;
if ( ! role_snapshot ) {
return ;
}
@ -636,40 +685,49 @@ void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, cons
role_snapshot - > snapshot = snapshot ;
ao2_ref ( role_snapshot - > snapshot , + 1 ) ;
ao2_link ( obj - > channel_snapshots , role_snapshot ) ;
ao2_ref ( role_snapshot , - 1 ) ;
}
struct ast_channel_snapshot * ast_multi_channel_blob_get_channel ( struct ast_multi_channel_blob * obj , const char * role )
{
struct channel_role_snapshot * role_snapshot ;
struct ast_channel_snapshot * snapshot ;
if ( ! obj | | ast_strlen_zero ( role ) ) {
return NULL ;
}
role_snapshot = ao2_find ( obj - > channel_snapshots , role , OBJ_ KEY) ;
role_snapshot = ao2_find ( obj - > channel_snapshots , role , OBJ_ SEARCH_ KEY) ;
/* Note that this function does not increase the ref count on snapshot */
if ( ! role_snapshot ) {
return NULL ;
}
snapshot = role_snapshot - > snapshot ;
ao2_ref ( role_snapshot , - 1 ) ;
return role_snapshot- > snapshot;
return snapshot;
}
struct ao2_container * ast_multi_channel_blob_get_channels ( struct ast_multi_channel_blob * obj , const char * role )
{
RAII_VAR ( struct ao2_container * , ret_container ,
ao2_container_alloc ( NUM_MULTI_CHANNEL_BLOB_BUCKETS , channel_snapshot_hash_cb , channel_snapshot_cmp_cb ) ,
ao2_cleanup ) ;
struct ao2_container * ret_container ;
struct ao2_iterator * it_role_snapshots ;
struct channel_role_snapshot * role_snapshot ;
char * arg ;
if ( ! obj | | ast_strlen_zero ( role ) | | ! ret_container ) {
if ( ! obj | | ast_strlen_zero ( role ) ) {
return NULL ;
}
arg = ast_strdupa ( role ) ;
it_role_snapshots = ao2_callback ( obj - > channel_snapshots , OBJ_MULTIPLE | OBJ_KEY , channel_role_multi_cmp_cb , arg ) ;
ret_container = ao2_container_alloc ( NUM_MULTI_CHANNEL_BLOB_BUCKETS ,
channel_snapshot_hash_cb , channel_snapshot_cmp_cb ) ;
if ( ! ret_container ) {
return NULL ;
}
arg = ast_strdupa ( role ) ;
it_role_snapshots = ao2_callback ( obj - > channel_snapshots ,
OBJ_MULTIPLE | OBJ_SEARCH_KEY , channel_role_cmp_cb , arg ) ;
if ( ! it_role_snapshots ) {
ao2_ref ( ret_container , - 1 ) ;
return NULL ;
}
@ -679,7 +737,6 @@ struct ao2_container *ast_multi_channel_blob_get_channels(struct ast_multi_chann
}
ao2_iterator_destroy ( it_role_snapshots ) ;
ao2_ref ( ret_container , + 1 ) ;
return ret_container ;
}
@ -704,8 +761,8 @@ void ast_channel_stage_snapshot_done(struct ast_channel *chan)
void ast_channel_publish_snapshot ( struct ast_channel * chan )
{
RAII_VAR ( struct ast_channel_snapshot * , snapshot , NULL , ao2_cleanup ) ;
RAII_VAR ( struct stasis_message * , message , NULL , ao2_cleanup ) ;
struct ast_channel_snapshot * snapshot ;
struct stasis_message * message ;
if ( ! ast_channel_snapshot_type ( ) ) {
return ;
@ -721,12 +778,14 @@ void ast_channel_publish_snapshot(struct ast_channel *chan)
}
message = stasis_message_create ( ast_channel_snapshot_type ( ) , snapshot ) ;
ao2_ref ( snapshot , - 1 ) ;
if ( ! message ) {
return ;
}
ast_assert ( ast_channel_topic ( chan ) ! = NULL ) ;
stasis_publish ( ast_channel_topic ( chan ) , message ) ;
ao2_ref ( message , - 1 ) ;
}
void ast_channel_publish_cached_blob ( struct ast_channel * chan , struct stasis_message_type * type , struct ast_json * blob )
@ -740,8 +799,8 @@ void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_mes
message = ast_channel_blob_create_from_cache ( ast_channel_uniqueid ( chan ) , type , blob ) ;
if ( message ) {
stasis_publish ( ast_channel_topic ( chan ) , message ) ;
ao2_ref ( message , - 1 ) ;
}
ao2_cleanup ( message ) ;
}
void ast_channel_publish_blob ( struct ast_channel * chan , struct stasis_message_type * type , struct ast_json * blob )
@ -755,8 +814,8 @@ void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_ty
message = ast_channel_blob_create ( chan , type , blob ) ;
if ( message ) {
stasis_publish ( ast_channel_topic ( chan ) , message ) ;
ao2_ref ( message , - 1 ) ;
}
ao2_cleanup ( message ) ;
}
void ast_channel_publish_varset ( struct ast_channel * chan , const char * name , const char * value )
@ -791,78 +850,88 @@ void ast_channel_publish_varset(struct ast_channel *chan, const char *name, cons
static struct ast_manager_event_blob * varset_to_ami ( struct stasis_message * msg )
{
RAII_VAR ( struct ast_str * , channel_event_string , NULL , ast_free ) ;
struct ast_str * channel_event_string ;
struct ast_channel_blob * obj = stasis_message_data ( msg ) ;
const char * variable =
ast_json_string_get ( ast_json_object_get ( obj - > blob , " variable " ) ) ;
RAII_VAR ( char * , value , ast_escape_c_alloc (
ast_json_string_get ( ast_json_object_get ( obj - > blob , " value " ) ) ) , ast_free ) ;
char * value ;
struct ast_manager_event_blob * ev ;
value = ast_escape_c_alloc ( ast_json_string_get ( ast_json_object_get ( obj - > blob ,
" value " ) ) ) ;
if ( ! value ) {
return NULL ;
}
if ( obj - > snapshot ) {
channel_event_string =
ast_manager_build_channel_state_string ( obj - > snapshot ) ;
channel_event_string = ast_manager_build_channel_state_string ( obj - > snapshot ) ;
} else {
channel_event_string = ast_str_create ( 35 ) ;
ast_str_set ( & channel_event_string , 0 ,
" Channel: none \r \n "
" Uniqueid: none \r \n " ) ;
" Channel: none \r \n "
" Uniqueid: none \r \n " ) ;
}
if ( ! channel_event_string ) {
ast_free ( value ) ;
return NULL ;
}
return ast_manager_event_blob_create ( EVENT_FLAG_DIALPLAN , " VarSet " ,
ev = ast_manager_event_blob_create ( EVENT_FLAG_DIALPLAN , " VarSet " ,
" %s "
" Variable: %s \r \n "
" Value: %s \r \n " ,
ast_str_buffer ( channel_event_string ) , variable , value ) ;
ast_free ( channel_event_string ) ;
ast_free ( value ) ;
return ev ;
}
static struct ast_manager_event_blob * agent_login_to_ami ( struct stasis_message * msg )
{
RAII_VAR ( struct ast_str * , channel_string , NULL , ast_free ) ;
struct ast_str * channel_string ;
struct ast_channel_blob * obj = stasis_message_data ( msg ) ;
const char * agent = ast_json_string_get ( ast_json_object_get ( obj - > blob , " agent " ) ) ;
struct ast_manager_event_blob * ev ;
channel_string = ast_manager_build_channel_state_string ( obj - > snapshot ) ;
if ( ! channel_string ) {
return NULL ;
}
return ast_manager_event_blob_create ( EVENT_FLAG_AGENT , " AgentLogin " ,
ev = ast_manager_event_blob_create ( EVENT_FLAG_AGENT , " AgentLogin " ,
" %s "
" Agent: %s \r \n " ,
ast_str_buffer ( channel_string ) , agent ) ;
ast_free ( channel_string ) ;
return ev ;
}
static struct ast_manager_event_blob * agent_logoff_to_ami ( struct stasis_message * msg )
{
RAII_VAR ( struct ast_str * , channel_string , NULL , ast_free ) ;
struct ast_str * channel_string ;
struct ast_channel_blob * obj = stasis_message_data ( msg ) ;
const char * agent = ast_json_string_get ( ast_json_object_get ( obj - > blob , " agent " ) ) ;
long logintime = ast_json_integer_get ( ast_json_object_get ( obj - > blob , " logintime " ) ) ;
struct ast_manager_event_blob * ev ;
channel_string = ast_manager_build_channel_state_string ( obj - > snapshot ) ;
if ( ! channel_string ) {
return NULL ;
}
return ast_manager_event_blob_create ( EVENT_FLAG_AGENT , " AgentLogoff " ,
ev = ast_manager_event_blob_create ( EVENT_FLAG_AGENT , " AgentLogoff " ,
" %s "
" Agent: %s \r \n "
" Logintime: %ld \r \n " ,
ast_str_buffer ( channel_string ) , agent , logintime ) ;
ast_free ( channel_string ) ;
return ev ;
}
void ast_publish_channel_state ( struct ast_channel * chan )
{
RAII_VAR ( struct ast_channel_snapshot * , snapshot , NULL , ao2_cleanup ) ;
RAII_VAR ( struct stasis_message * , message , NULL , ao2_cleanup ) ;
struct ast_channel_snapshot * snapshot ;
struct stasis_message * message ;
if ( ! ast_channel_snapshot_type ( ) ) {
return ;
@ -879,12 +948,14 @@ void ast_publish_channel_state(struct ast_channel *chan)
}
message = stasis_message_create ( ast_channel_snapshot_type ( ) , snapshot ) ;
ao2_ref ( snapshot , - 1 ) ;
if ( ! message ) {
return ;
}
ast_assert ( ast_channel_topic ( chan ) ! = NULL ) ;
stasis_publish ( ast_channel_topic ( chan ) , message ) ;
ao2_ref ( message , - 1 ) ;
}
struct ast_json * ast_channel_snapshot_to_json (
@ -894,8 +965,9 @@ struct ast_json *ast_channel_snapshot_to_json(
struct ast_json * json_chan ;
if ( snapshot = = NULL
| | ( sanitize & & sanitize - > channel_snapshot
& & sanitize - > channel_snapshot ( snapshot ) ) ) {
| | ( sanitize
& & sanitize - > channel_snapshot
& & sanitize - > channel_snapshot ( snapshot ) ) ) {
return NULL ;
}
@ -969,7 +1041,7 @@ static struct ast_json *channel_blob_to_json(
const char * type ,
const struct stasis_message_sanitizer * sanitize )
{
RAII_VAR ( struct ast_json * , out , NULL , ast_json_unref ) ;
struct ast_json * to_json ;
struct ast_channel_blob * channel_blob = stasis_message_data ( message ) ;
struct ast_json * blob = channel_blob - > blob ;
struct ast_channel_snapshot * snapshot = channel_blob - > snapshot ;
@ -977,36 +1049,38 @@ static struct ast_json *channel_blob_to_json(
int res = 0 ;
if ( blob = = NULL | | ast_json_is_null ( blob ) ) {
ou t = ast_json_object_create ( ) ;
to_json = ast_json_object_create ( ) ;
} else {
/* blobs are immutable, so shallow copies are fine */
ou t = ast_json_copy ( blob ) ;
to_json = ast_json_copy ( blob ) ;
}
if ( ! out ) {
if ( ! to_json ) {
return NULL ;
}
res | = ast_json_object_set ( ou t, " type " , ast_json_string_create ( type ) ) ;
res | = ast_json_object_set ( ou t, " timestamp " ,
res | = ast_json_object_set ( to_json , " type " , ast_json_string_create ( type ) ) ;
res | = ast_json_object_set ( to_json , " timestamp " ,
ast_json_timeval ( * tv , NULL ) ) ;
/* For global channel messages, the snapshot is optional */
if ( snapshot ) {
struct ast_json * json_channel = ast_channel_snapshot_to_json ( snapshot , sanitize ) ;
struct ast_json * json_channel ;
json_channel = ast_channel_snapshot_to_json ( snapshot , sanitize ) ;
if ( ! json_channel ) {
ast_json_unref ( to_json ) ;
return NULL ;
}
res | = ast_json_object_set ( ou t, " channel " , json_channel ) ;
res | = ast_json_object_set ( to_json , " channel " , json_channel ) ;
}
if ( res ! = 0 ) {
ast_json_unref ( to_json ) ;
return NULL ;
}
return ast_json_ref ( out ) ;
return to_json ;
}
static struct ast_json * dtmf_end_to_json (