SWITCH_DECLARE(const char *) CoreSession::getState() { this_check(NULL); if (channel) { return switch_channel_state_name(switch_channel_get_state(channel)); } return "ERROR"; }
static void check_presence(switch_core_session_t *session) { switch_channel_state_t state = switch_channel_get_running_state(session->channel); if (state == CS_ROUTING || state == CS_HANGUP) { if (switch_channel_get_cause(session->channel) == SWITCH_CAUSE_LOSE_RACE) { switch_channel_presence(session->channel, "unknown", "cancelled", NULL); switch_channel_set_variable(session->channel, "presence_call_info", NULL); } else { switch_channel_presence(session->channel, "unknown", switch_channel_state_name(state), NULL); } } }
static switch_status_t my_on_reporting(switch_core_session_t *session) { switch_status_t status = SWITCH_STATUS_SUCCESS; switch_channel_t *channel = switch_core_session_get_channel(session); switch_event_header_t *hi; switch_caller_profile_t *caller_profile; switch_app_log_t *app_log; bson cdr; int is_b; char *tmp; if (globals.shutdown) { return SWITCH_STATUS_SUCCESS; } is_b = channel && switch_channel_get_originator_caller_profile(channel); if (!globals.log_b && is_b) { const char *force_cdr = switch_channel_get_variable(channel, SWITCH_FORCE_PROCESS_CDR_VARIABLE); if (!switch_true(force_cdr)) { return SWITCH_STATUS_SUCCESS; } } bson_init(&cdr); /* Channel data */ bson_append_start_object(&cdr, "channel_data"); bson_append_string(&cdr, "state", switch_channel_state_name(switch_channel_get_state(channel))); bson_append_string(&cdr, "direction", switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"); bson_append_int(&cdr, "state_number", switch_channel_get_state(channel)); if ((tmp = switch_channel_get_flag_string(channel))) { bson_append_string(&cdr, "flags", tmp); free(tmp); } if ((tmp = switch_channel_get_cap_string(channel))) { bson_append_string(&cdr, "caps", tmp); free(tmp); } bson_append_finish_object(&cdr); /* channel_data */ /* Channel variables */ bson_append_start_object(&cdr, "variables"); if ((hi = switch_channel_variable_first(channel))) { for (; hi; hi = hi->next) { if (!zstr(hi->name) && !zstr(hi->value)) { bson_append_string(&cdr, hi->name, hi->value); } } switch_channel_variable_last(channel); } bson_append_finish_object(&cdr); /* variables */ /* App log */ if ((app_log = switch_core_session_get_app_log(session))) { switch_app_log_t *ap; bson_append_start_object(&cdr, "app_log"); for (ap = app_log; ap; ap = ap->next) { bson_append_start_object(&cdr, "application"); bson_append_string(&cdr, "app_name", ap->app); bson_append_string(&cdr, "app_data", ap->arg); bson_append_long(&cdr, "app_stamp", ap->stamp); bson_append_finish_object(&cdr); /* application */ } bson_append_finish_object(&cdr); /* app_log */ } /* Callflow */ caller_profile = switch_channel_get_caller_profile(channel); while (caller_profile) { bson_append_start_object(&cdr, "callflow"); if (!zstr(caller_profile->dialplan)) { bson_append_string(&cdr, "dialplan", caller_profile->dialplan); } if (!zstr(caller_profile->profile_index)) { bson_append_string(&cdr, "profile_index", caller_profile->profile_index); } if (caller_profile->caller_extension) { switch_caller_application_t *ap; bson_append_start_object(&cdr, "extension"); bson_append_string(&cdr, "name", caller_profile->caller_extension->extension_name); bson_append_string(&cdr, "number", caller_profile->caller_extension->extension_number); if (caller_profile->caller_extension->current_application) { bson_append_string(&cdr, "current_app", caller_profile->caller_extension->current_application->application_name); } for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) { bson_append_start_object(&cdr, "application"); if (ap == caller_profile->caller_extension->current_application) { bson_append_bool(&cdr, "last_executed", 1); } bson_append_string(&cdr, "app_name", ap->application_name); bson_append_string(&cdr, "app_data", ap->application_data); bson_append_finish_object(&cdr); } if (caller_profile->caller_extension->children) { switch_caller_profile_t *cp = NULL; for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) { if (!cp->caller_extension) { continue; } bson_append_start_object(&cdr, "sub_extensions"); bson_append_start_object(&cdr, "extension"); bson_append_string(&cdr, "name", cp->caller_extension->extension_name); bson_append_string(&cdr, "number", cp->caller_extension->extension_number); bson_append_string(&cdr, "dialplan", cp->dialplan); if (cp->caller_extension->current_application) { bson_append_string(&cdr, "current_app", cp->caller_extension->current_application->application_name); } for (ap = cp->caller_extension->applications; ap; ap = ap->next) { bson_append_start_object(&cdr, "application"); if (ap == cp->caller_extension->current_application) { bson_append_bool(&cdr, "last_executed", 1); } bson_append_string(&cdr, "app_name", ap->application_name); bson_append_string(&cdr, "app_data", ap->application_data); bson_append_finish_object(&cdr); } bson_append_finish_object(&cdr); /* extension */ bson_append_finish_object(&cdr); /* sub_extensions */ } } bson_append_finish_object(&cdr); /* extension */ } bson_append_start_object(&cdr, "caller_profile"); set_bson_profile_data(&cdr, caller_profile); if (caller_profile->origination_caller_profile) { switch_caller_profile_t *cp = NULL; bson_append_start_object(&cdr, "origination"); for (cp = caller_profile->origination_caller_profile; cp; cp = cp->next) { bson_append_start_object(&cdr, "origination_caller_profile"); set_bson_profile_data(&cdr, cp); bson_append_finish_object(&cdr); } bson_append_finish_object(&cdr); /* origination */ } if (caller_profile->originator_caller_profile) { switch_caller_profile_t *cp = NULL; bson_append_start_object(&cdr, "originator"); for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) { bson_append_start_object(&cdr, "originator_caller_profile"); set_bson_profile_data(&cdr, cp); bson_append_finish_object(&cdr); } bson_append_finish_object(&cdr); /* originator */ } if (caller_profile->originatee_caller_profile) { switch_caller_profile_t *cp = NULL; bson_append_start_object(&cdr, "originatee"); for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) { bson_append_start_object(&cdr, "originatee_caller_profile"); set_bson_profile_data(&cdr, cp); bson_append_finish_object(&cdr); } bson_append_finish_object(&cdr); /* originatee */ } bson_append_finish_object(&cdr); /* caller_profile */ /* Timestamps */ if (caller_profile->times) { bson_append_start_object(&cdr, "times"); /* Insert timestamps as long ints (microseconds) to preserve accuracy */ bson_append_long(&cdr, "created_time", caller_profile->times->created); bson_append_long(&cdr, "profile_created_time", caller_profile->times->profile_created); bson_append_long(&cdr, "progress_time", caller_profile->times->progress); bson_append_long(&cdr, "progress_media_time", caller_profile->times->progress_media); bson_append_long(&cdr, "answered_time", caller_profile->times->answered); bson_append_long(&cdr, "bridged_time", caller_profile->times->bridged); bson_append_long(&cdr, "last_hold_time", caller_profile->times->last_hold); bson_append_long(&cdr, "hold_accum_time", caller_profile->times->hold_accum); bson_append_long(&cdr, "hangup_time", caller_profile->times->hungup); bson_append_long(&cdr, "resurrect_time", caller_profile->times->resurrected); bson_append_long(&cdr, "transfer_time", caller_profile->times->transferred); bson_append_finish_object(&cdr); /* times */ } bson_append_finish_object(&cdr); /* callflow */ caller_profile = caller_profile->next; } bson_finish(&cdr); switch_mutex_lock(globals.mongo_mutex); if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr) != MONGO_OK) { if (globals.mongo_conn->err == MONGO_IO_ERROR) { mongo_error_t db_status; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MongoDB connection failed; attempting reconnect...\n"); db_status = mongo_reconnect(globals.mongo_conn); if (db_status != MONGO_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MongoDB reconnect failed with error code %d\n", db_status); status = SWITCH_STATUS_FALSE; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MongoDB connection re-established.\n"); if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr) != MONGO_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err); status = SWITCH_STATUS_FALSE; } } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err); status = SWITCH_STATUS_FALSE; } } switch_mutex_unlock(globals.mongo_mutex); bson_destroy(&cdr); return status; }
SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) { switch_channel_state_t state = CS_NEW, midstate = CS_DESTROY, endstate; const switch_endpoint_interface_t *endpoint_interface; const switch_state_handler_table_t *driver_state_handler = NULL; const switch_state_handler_table_t *application_state_handler = NULL; int silly = 0; uint32_t new_loops = 500; /* Life of the channel. you have channel and pool in your session everywhere you go you use the session to malloc with switch_core_session_alloc(session, <size>) The endpoint module gets the first crack at implementing the state if it wants to, it can cancel the default behavior by returning SWITCH_STATUS_FALSE Next comes the channel's event handler table that can be set by an application which also can veto the next behavior in line by returning SWITCH_STATUS_FALSE Finally the default state behavior is called. */ switch_assert(session != NULL); switch_set_flag(session, SSF_THREAD_RUNNING); endpoint_interface = session->endpoint_interface; switch_assert(endpoint_interface != NULL); driver_state_handler = endpoint_interface->state_handler; switch_assert(driver_state_handler != NULL); switch_mutex_lock(session->mutex); while ((state = switch_channel_get_state(session->channel)) != CS_DESTROY) { if (switch_channel_test_flag(session->channel, CF_BLOCK_STATE)) { switch_channel_wait_for_flag(session->channel, CF_BLOCK_STATE, SWITCH_FALSE, 0, NULL); if ((state = switch_channel_get_state(session->channel)) == CS_DESTROY) { break; } } midstate = state; if (state != switch_channel_get_running_state(session->channel) || state >= CS_HANGUP) { int index = 0; int proceed = 1; int global_proceed = 1; int do_extra_handlers = 1; switch_io_event_hook_state_run_t *ptr; switch_status_t rstatus = SWITCH_STATUS_SUCCESS; switch_channel_set_running_state(session->channel, state); switch_channel_clear_flag(session->channel, CF_TRANSFER); switch_channel_clear_flag(session->channel, CF_REDIRECT); if (session->endpoint_interface->io_routines->state_run) { rstatus = session->endpoint_interface->io_routines->state_run(session); } if (rstatus == SWITCH_STATUS_SUCCESS) { for (ptr = session->event_hooks.state_run; ptr; ptr = ptr->next) { if ((rstatus = ptr->state_run(session)) != SWITCH_STATUS_SUCCESS) { break; } } } switch (state) { case CS_NEW: /* Just created, Waiting for first instructions */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) State NEW\n", switch_channel_get_name(session->channel)); break; case CS_DESTROY: goto done; case CS_REPORTING: /* Call Detail */ { switch_core_session_reporting_state(session); switch_channel_set_state(session->channel, CS_DESTROY); } goto done; case CS_HANGUP: /* Deactivate and end the thread */ { switch_core_session_hangup_state(session, SWITCH_TRUE); switch_channel_set_state(session->channel, CS_REPORTING); } break; case CS_INIT: /* Basic setup tasks */ { switch_event_t *event; STATE_MACRO(init, "INIT"); if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CREATE) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_ORIGINATE) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } } } break; case CS_ROUTING: /* Look for a dialplan and find something to do */ STATE_MACRO(routing, "ROUTING"); break; case CS_RESET: /* Reset */ STATE_MACRO(reset, "RESET"); break; /* These other states are intended for prolonged durations so we do not signal lock for them */ case CS_EXECUTE: /* Execute an Operation */ STATE_MACRO(execute, "EXECUTE"); break; case CS_EXCHANGE_MEDIA: /* loop all data back to source */ STATE_MACRO(exchange_media, "EXCHANGE_MEDIA"); break; case CS_SOFT_EXECUTE: /* send/recieve data to/from another channel */ STATE_MACRO(soft_execute, "SOFT_EXECUTE"); break; case CS_PARK: /* wait in limbo */ STATE_MACRO(park, "PARK"); break; case CS_CONSUME_MEDIA: /* wait in limbo */ STATE_MACRO(consume_media, "CONSUME_MEDIA"); break; case CS_HIBERNATE: /* sleep */ STATE_MACRO(hibernate, "HIBERNATE"); break; case CS_NONE: abort(); break; } check_presence(session); if (midstate == CS_DESTROY) { break; } } endstate = switch_channel_get_state(session->channel); if (endstate == switch_channel_get_running_state(session->channel)) { if (endstate == CS_NEW) { switch_yield(20000); switch_ivr_parse_all_events(session); if (!--new_loops) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s %s Abandoned\n", session->uuid_str, switch_core_session_get_name(session)); switch_channel_set_flag(session->channel, CF_NO_CDR); switch_channel_hangup(session->channel, SWITCH_CAUSE_WRONG_CALL_STATE); } } else { switch_ivr_parse_all_events(session); switch_ivr_parse_all_events(session); if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { switch_channel_state_thread_lock(session->channel); switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING); if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { switch_ivr_parse_all_events(session); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread sleep state: %s!\n", switch_channel_get_name(session->channel), switch_channel_state_name(switch_channel_get_running_state(session->channel))); switch_thread_cond_wait(session->cond, session->mutex); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread wake state: %s!\n", switch_channel_get_name(session->channel), switch_channel_state_name(switch_channel_get_running_state(session->channel))); } switch_channel_clear_flag(session->channel, CF_THREAD_SLEEPING); switch_channel_state_thread_unlock(session->channel); } switch_ivr_parse_all_events(session); switch_ivr_parse_all_events(session); } } } done: switch_mutex_unlock(session->mutex); switch_clear_flag(session, SSF_THREAD_RUNNING); }
static switch_status_t generate_json_cdr(switch_core_session_t *session, struct json_object **json_cdr) { struct json_object *cdr = json_object_new_object(); switch_channel_t *channel = switch_core_session_get_channel(session); switch_caller_profile_t *caller_profile; struct json_object *variables, *j_main_cp, *j_caller_profile, *j_caller_extension, *j_times, *time_tag, *j_application, *j_callflow, *j_inner_extension, *j_apps, *j_o, *j_channel_data, *j_field; switch_app_log_t *app_log; char tmp[512], *f; if (is_error(cdr)) { return SWITCH_STATUS_FALSE; } j_channel_data = json_object_new_object(); if (is_error(j_channel_data)) { goto error; } json_object_object_add(cdr, "channel_data", j_channel_data); j_field = json_object_safe_new_string((char *) switch_channel_state_name(switch_channel_get_state(channel))); json_object_object_add(j_channel_data, "state", j_field); j_field = json_object_safe_new_string(switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"); json_object_object_add(j_channel_data, "direction", j_field); switch_snprintf(tmp, sizeof(tmp), "%d", switch_channel_get_state(channel)); j_field = json_object_new_string((char *) tmp); json_object_object_add(j_channel_data, "state_number", j_field); if ((f = switch_channel_get_flag_string(channel))) { j_field = json_object_safe_new_string((char *) f); json_object_object_add(j_channel_data, "flags", j_field); free(f); } if ((f = switch_channel_get_cap_string(channel))) { j_field = json_object_safe_new_string((char *) f); json_object_object_add(j_channel_data, "caps", j_field); free(f); } variables = json_object_new_object(); json_object_object_add(cdr, "variables", variables); if (is_error(variables)) { goto error; } set_json_chan_vars(variables, channel); if ((app_log = switch_core_session_get_app_log(session))) { switch_app_log_t *ap; j_apps = json_object_new_object(); if (is_error(j_apps)) { goto error; } json_object_object_add(cdr, "app_log", j_apps); for (ap = app_log; ap; ap = ap->next) { j_application = json_object_new_object(); if (is_error(j_application)) { goto error; } json_object_object_add(j_application, "app_name", json_object_safe_new_string(ap->app)); json_object_object_add(j_application, "app_data", json_object_safe_new_string(ap->arg)); json_object_object_add(j_apps, "application", j_application); } } caller_profile = switch_channel_get_caller_profile(channel); while (caller_profile) { j_callflow = json_object_new_object(); if (is_error(j_callflow)) { goto error; } json_object_object_add(cdr, "callflow", j_callflow); if (!zstr(caller_profile->dialplan)) { json_object_object_add(j_callflow, "dialplan", json_object_safe_new_string((char *)caller_profile->dialplan)); } if (!zstr(caller_profile->profile_index)) { json_object_object_add(j_callflow, "profile_index", json_object_safe_new_string((char *)caller_profile->profile_index)); } if (caller_profile->caller_extension) { switch_caller_application_t *ap; j_caller_extension = json_object_new_object(); if (is_error(j_caller_extension)) { goto error; } json_object_object_add(j_callflow, "extension", j_caller_extension); json_object_object_add(j_caller_extension, "name", json_object_safe_new_string(caller_profile->caller_extension->extension_name)); json_object_object_add(j_caller_extension, "number", json_object_safe_new_string(caller_profile->caller_extension->extension_number)); if (caller_profile->caller_extension->current_application) { json_object_object_add(j_caller_extension, "current_app", json_object_safe_new_string(caller_profile->caller_extension->current_application->application_name)); } for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) { j_application = json_object_new_object(); if (is_error(j_application)) { goto error; } json_object_object_add(j_caller_extension, "application", j_application); if (ap == caller_profile->caller_extension->current_application) { json_object_object_add(j_application, "last_executed", json_object_new_string("true")); } json_object_object_add(j_application, "app_name", json_object_safe_new_string(ap->application_name)); json_object_object_add(j_application, "app_data", json_object_safe_new_string(switch_str_nil(ap->application_data))); } if (caller_profile->caller_extension->children) { switch_caller_profile_t *cp = NULL; for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) { if (!cp->caller_extension) { continue; } j_inner_extension = json_object_new_object(); if (is_error(j_inner_extension)) { goto error; } json_object_object_add(j_caller_extension, "sub_extensions", j_inner_extension); j_caller_extension = json_object_new_object(); if (is_error(j_caller_extension)) { goto error; } json_object_object_add(j_inner_extension, "extension", j_caller_extension); json_object_object_add(j_caller_extension, "name", json_object_safe_new_string(cp->caller_extension->extension_name)); json_object_object_add(j_caller_extension, "number", json_object_safe_new_string(cp->caller_extension->extension_number)); json_object_object_add(j_caller_extension, "dialplan", json_object_safe_new_string((char *)cp->dialplan)); if (cp->caller_extension->current_application) { json_object_object_add(j_caller_extension, "current_app", json_object_safe_new_string(cp->caller_extension->current_application->application_name)); } for (ap = cp->caller_extension->applications; ap; ap = ap->next) { j_application = json_object_new_object(); if (is_error(j_application)) { goto error; } json_object_object_add(j_caller_extension, "application", j_application); if (ap == cp->caller_extension->current_application) { json_object_object_add(j_application, "last_executed", json_object_new_string("true")); } json_object_object_add(j_application, "app_name", json_object_safe_new_string(ap->application_name)); json_object_object_add(j_application, "app_data", json_object_safe_new_string(switch_str_nil(ap->application_data))); } } } } j_main_cp = json_object_new_object(); if (is_error(j_main_cp)) { goto error; } json_object_object_add(j_callflow, "caller_profile", j_main_cp); set_json_profile_data(j_main_cp, caller_profile); if (caller_profile->originator_caller_profile) { switch_caller_profile_t *cp = NULL; j_o = json_object_new_object(); if (is_error(j_o)) { goto error; } json_object_object_add(j_main_cp, "originator", j_o); for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) { j_caller_profile = json_object_new_object(); if (is_error(j_caller_profile)) { goto error; } json_object_object_add(j_o, "originator_caller_profile", j_caller_profile); set_json_profile_data(j_caller_profile, cp); } } if (caller_profile->originatee_caller_profile) { switch_caller_profile_t *cp = NULL; j_o = json_object_new_object(); if (is_error(j_o)) { goto error; } json_object_object_add(j_main_cp, "originatee", j_o); for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) { j_caller_profile = json_object_new_object(); if (is_error(j_caller_profile)) { goto error; } json_object_object_add(j_o, "originatee_caller_profile", j_caller_profile); set_json_profile_data(j_caller_profile, cp); } } if (caller_profile->times) { j_times = json_object_new_object(); if (is_error(j_times)) { goto error; } json_object_object_add(j_callflow, "times", j_times); switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->created); time_tag = json_object_new_string(tmp); if (is_error(time_tag)) { goto error; } json_object_object_add(j_times, "created_time", time_tag); switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->profile_created); time_tag = json_object_new_string(tmp); if (is_error(time_tag)) { goto error; } json_object_object_add(j_times, "profile_created_time", time_tag); switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress); time_tag = json_object_new_string(tmp); if (is_error(time_tag)) { goto error; } json_object_object_add(j_times, "progress_time", time_tag); switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress_media); time_tag = json_object_new_string(tmp); if (is_error(time_tag)) { goto error; } json_object_object_add(j_times, "progress_media_time", time_tag); switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered); time_tag = json_object_new_string(tmp); if (is_error(time_tag)) { goto error; } json_object_object_add(j_times, "answered_time", time_tag); switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hungup); time_tag = json_object_new_string(tmp); if (is_error(time_tag)) { goto error; } json_object_object_add(j_times, "hangup_time", time_tag); switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->resurrected); time_tag = json_object_new_string(tmp); if (is_error(time_tag)) { goto error; } json_object_object_add(j_times, "resurrect_time", time_tag); switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->transferred); time_tag = json_object_new_string(tmp); if (is_error(time_tag)) { goto error; } json_object_object_add(j_times, "transfer_time", time_tag); } caller_profile = caller_profile->next; } *json_cdr = cdr; return SWITCH_STATUS_SUCCESS; error: if (cdr) { json_object_put(cdr); } return SWITCH_STATUS_FALSE; }