]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add bridged timestamp and hangup_complete_with_xml=true to add xml_cdr to the body...
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 28 Apr 2011 18:46:39 +0000 (13:46 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 28 Apr 2011 18:46:39 +0000 (13:46 -0500)
src/include/switch_channel.h
src/include/switch_utils.h
src/switch_channel.c
src/switch_core_state_machine.c
src/switch_ivr.c
src/switch_ivr_bridge.c

index febaf40f75f5a4bf185fc6986d6e50625091f40c..dc8175b202245b626e9801b553446d2b4b0877a4 100644 (file)
@@ -49,6 +49,7 @@ SWITCH_BEGIN_EXTERN_C struct switch_channel_timetable {
        switch_time_t hungup;
        switch_time_t transferred;
        switch_time_t resurrected;
+       switch_time_t bridged;
        struct switch_channel_timetable *next;
 };
 
@@ -597,7 +598,7 @@ SWITCH_DECLARE(int) switch_channel_test_app_flag_key(const char *app, switch_cha
 #define switch_channel_clear_app_flag(_c, _f) switch_channel_clear_app_flag_key(__FILE__, _c, _f)
 #define switch_channel_test_app_flag(_c, _f) switch_channel_test_app_flag_key(__FILE__, _c, _f)
 
-
+SWITCH_DECLARE(void) switch_channel_set_bridge_time(switch_channel_t *channel);
 SWITCH_DECLARE(void) switch_channel_set_hangup_time(switch_channel_t *channel);
 SWITCH_DECLARE(switch_call_direction_t) switch_channel_direction(switch_channel_t *channel);
 SWITCH_DECLARE(switch_core_session_t *) switch_channel_get_session(switch_channel_t *channel);
index 4135ade0919d2ebe80cefbc51c78110e13b0a711..88c13379b30bd48d265ad11f95c37bf12ac091b9 100644 (file)
@@ -239,20 +239,23 @@ SWITCH_DECLARE(switch_size_t) switch_fd_read_line(int fd, char *buf, switch_size
 SWITCH_DECLARE(switch_status_t) switch_frame_alloc(switch_frame_t **frame, switch_size_t size);
 SWITCH_DECLARE(switch_status_t) switch_frame_dup(switch_frame_t *orig, switch_frame_t **clone);
 SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame);
+SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str);
 
 /*!
   \brief Evaluate the truthfullness of a string expression
   \param expr a string expression
   \return true or false 
 */
-#define switch_true(expr)\
-((expr && ( !strcasecmp(expr, "yes") ||\
-!strcasecmp(expr, "on") ||\
-!strcasecmp(expr, "true") ||\
-!strcasecmp(expr, "enabled") ||\
-!strcasecmp(expr, "active") ||\
-!strcasecmp(expr, "allow") ||\
-(switch_is_number(expr) && atoi(expr)))) ? SWITCH_TRUE : SWITCH_FALSE)
+static inline int switch_true(const char *expr) 
+{
+       return ((expr && ( !strcasecmp(expr, "yes") ||  
+                                          !strcasecmp(expr, "on") ||   
+                                          !strcasecmp(expr, "true") || 
+                                          !strcasecmp(expr, "enabled") ||      
+                                          !strcasecmp(expr, "active") ||       
+                                          !strcasecmp(expr, "allow") ||                                        
+                                          (switch_is_number(expr) && atoi(expr)))) ? SWITCH_TRUE : SWITCH_FALSE);
+}
 
 #define switch_true_buf(expr)\
 ((( !strcasecmp(expr, "yes") ||\
@@ -268,14 +271,16 @@ SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame);
   \param expr a string expression
   \return true or false 
 */
-#define switch_false(expr)\
-((expr && ( !strcasecmp(expr, "no") ||\
-!strcasecmp(expr, "off") ||\
-!strcasecmp(expr, "false") ||\
-!strcasecmp(expr, "disabled") ||\
-!strcasecmp(expr, "inactive") ||\
-!strcasecmp(expr, "disallow") ||\
-(switch_is_number(expr) && !atoi(expr)))) ? SWITCH_TRUE : SWITCH_FALSE)
+static inline int switch_false(const char *expr)
+{
+       return ((expr && ( !strcasecmp(expr, "no") ||
+                                          !strcasecmp(expr, "off") ||
+                                          !strcasecmp(expr, "false") ||
+                                          !strcasecmp(expr, "disabled") ||
+                                          !strcasecmp(expr, "inactive") ||
+                                          !strcasecmp(expr, "disallow") ||
+                                          (switch_is_number(expr) && !atoi(expr)))) ? SWITCH_TRUE : SWITCH_FALSE);
+}
 
 
 SWITCH_DECLARE(switch_status_t) switch_resolve_host(const char *host, char *buf, size_t buflen);
@@ -670,7 +675,7 @@ SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in);
 SWITCH_DECLARE(unsigned int) switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen);
 SWITCH_DECLARE(unsigned int) switch_separate_string_string(char *buf, char *delim, _Post_count_(return) char **array, unsigned int arraylen);
 
-SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str);
+
 SWITCH_DECLARE(char *) switch_strip_spaces(char *str, switch_bool_t dup);
 SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str);
 SWITCH_DECLARE(char *) switch_strip_commas(char *in, char *out, switch_size_t len);
index 2cd45b9e06ed50cafafd3e8f57e0b0db853a2c2c..5b1d06ce33f1ceef4c0e36cdbd813c691fb79756 100644 (file)
@@ -2513,11 +2513,21 @@ SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_caller_extension(
 }
 
 
+SWITCH_DECLARE(void) switch_channel_set_bridge_time(switch_channel_t *channel)
+{
+       switch_mutex_lock(channel->profile_mutex);
+       if (channel->caller_profile && channel->caller_profile->times) {
+               channel->caller_profile->times->bridged = switch_micro_time_now();
+       }
+       switch_mutex_unlock(channel->profile_mutex);
+}
+
+
 SWITCH_DECLARE(void) switch_channel_set_hangup_time(switch_channel_t *channel)
 {
-       if (channel->caller_profile && channel->caller_profile->times && !channel->caller_profile->times->hungup) {
+       if (channel->caller_profile && channel->caller_profile->times && !channel->caller_profile->times->bridged) {
                switch_mutex_lock(channel->profile_mutex);
-               channel->caller_profile->times->hungup = switch_micro_time_now();
+               channel->caller_profile->times->bridged = switch_micro_time_now();
                switch_mutex_unlock(channel->profile_mutex);
        }
 }
@@ -3348,14 +3358,14 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
        switch_caller_profile_t *caller_profile, *ocp;
        switch_app_log_t *app_log, *ap;
        char *last_app = NULL, *last_arg = NULL;
-       char start[80] = "", resurrect[80] = "", answer[80] = "", progress[80] = "", progress_media[80] = "", end[80] = "", tmp[80] = "",
+       char start[80] = "", resurrect[80] = "", answer[80] = "", bridge[80] = "", progress[80] = "", progress_media[80] = "", end[80] = "", tmp[80] = "",
                profile_start[80] =     "";
        int32_t duration = 0, legbillsec = 0, billsec = 0, mduration = 0, billmsec = 0, legbillmsec = 0, progressmsec = 0, progress_mediamsec = 0;
-       int32_t answersec = 0, answermsec = 0;
+       int32_t answersec = 0, answermsec = 0, waitsec = 0, waitmsec = 0;
        switch_time_t answerusec = 0;
-       switch_time_t uduration = 0, legbillusec = 0, billusec = 0, progresssec = 0, progressusec = 0, progress_mediasec = 0, progress_mediausec = 0;
-       time_t tt_created = 0, tt_answered = 0, tt_resurrected = 0,
-               tt_progress = 0, tt_progress_media = 0, tt_hungup = 0, mtt_created = 0, mtt_answered = 0,
+       switch_time_t uduration = 0, legbillusec = 0, billusec = 0, progresssec = 0, progressusec = 0, progress_mediasec = 0, progress_mediausec = 0, waitusec = 0;
+       time_t tt_created = 0, tt_answered = 0, tt_resurrected = 0, tt_bridged,
+               tt_progress = 0, tt_progress_media = 0, tt_hungup = 0, mtt_created = 0, mtt_answered = 0, mtt_bridged = 0,
                mtt_hungup = 0, tt_prof_created, mtt_prof_created, mtt_progress = 0, mtt_progress_media = 0;
        void *pop;
        char dtstr[SWITCH_DTMF_LOG_LEN + 1] = "";
@@ -3427,6 +3437,12 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
                        switch_channel_set_variable(channel, "answer_stamp", answer);
                }
 
+               if (caller_profile->times->bridged) {
+                       switch_time_exp_lt(&tm, caller_profile->times->bridged);
+                       switch_strftime_nocheck(bridge, &retsize, sizeof(bridge), fmt, &tm);
+                       switch_channel_set_variable(channel, "bridge_stamp", bridge);
+               }
+
                if (caller_profile->times->resurrected) {
                        switch_time_exp_lt(&tm, caller_profile->times->resurrected);
                        switch_strftime_nocheck(resurrect, &retsize, sizeof(resurrect), fmt, &tm);
@@ -3470,6 +3486,13 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
                switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
                switch_channel_set_variable(channel, "answer_uepoch", tmp);
 
+               tt_bridged = (time_t) (caller_profile->times->bridged / 1000000);
+               mtt_bridged = (time_t) (caller_profile->times->bridged / 1000);
+               switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_bridged);
+               switch_channel_set_variable(channel, "bridge_epoch", tmp);
+               switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged);
+               switch_channel_set_variable(channel, "bridge_uepoch", tmp);
+
                tt_resurrected = (time_t) (caller_profile->times->resurrected / 1000000);
                switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_resurrected);
                switch_channel_set_variable(channel, "resurrect_epoch", tmp);
@@ -3501,6 +3524,16 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
                mduration = (int32_t) (mtt_hungup - mtt_created);
                uduration = caller_profile->times->hungup - caller_profile->times->created;
 
+               if (caller_profile->times->bridged > caller_profile->times->created) {
+                       waitsec = (int32_t) (tt_bridged - tt_created);
+                       waitmsec = (int32_t) (mtt_bridged - mtt_created);
+                       waitusec = caller_profile->times->bridged - caller_profile->times->created;
+               } else {
+                       waitsec = 0;
+                       waitmsec = 0;
+                       waitusec = 0;
+               }
+
                if (caller_profile->times->answered) {
                        billsec = (int32_t) (tt_hungup - tt_answered);
                        billmsec = (int32_t) (mtt_hungup - mtt_answered);
@@ -3545,6 +3578,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
        switch_snprintf(tmp, sizeof(tmp), "%d", answersec);
        switch_channel_set_variable(channel, "answersec", tmp);
 
+       switch_snprintf(tmp, sizeof(tmp), "%d", waitsec);
+       switch_channel_set_variable(channel, "waitsec", tmp);
+
        switch_snprintf(tmp, sizeof(tmp), "%d", progress_mediasec);
        switch_channel_set_variable(channel, "progress_mediasec", tmp);
 
@@ -3563,6 +3599,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
        switch_snprintf(tmp, sizeof(tmp), "%d", answermsec);
        switch_channel_set_variable(channel, "answermsec", tmp);
 
+       switch_snprintf(tmp, sizeof(tmp), "%d", waitmsec);
+       switch_channel_set_variable(channel, "waitmsec", tmp);
+
        switch_snprintf(tmp, sizeof(tmp), "%d", progress_mediamsec);
        switch_channel_set_variable(channel, "progress_mediamsec", tmp);
 
@@ -3581,6 +3620,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
        switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, answerusec);
        switch_channel_set_variable(channel, "answerusec", tmp);
 
+       switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, waitusec);
+       switch_channel_set_variable(channel, "waitusec", tmp);
+
        switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, progress_mediausec);
        switch_channel_set_variable(channel, "progress_mediausec", tmp);
 
index e69c408013f861f558429f9798533a94a545fec9..6551b2b777b36bd61083f0833eb43b9642ba9b48 100644 (file)
@@ -636,6 +636,18 @@ SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t *
        if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE) == SWITCH_STATUS_SUCCESS) {
                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(cause));
                switch_channel_event_set_data(session->channel, event);
+               if (switch_true(switch_channel_get_variable(session->channel, "hangup_complete_with_xml"))) {
+                       switch_xml_t cdr = NULL;
+                       char *xml_cdr_text;
+                       
+                       if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) {
+                               xml_cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE);
+                               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CDR-Attached", "xml");
+                               switch_event_add_body(event, "%s", xml_cdr_text);
+                               switch_xml_free(cdr);
+                               switch_safe_free(xml_cdr_text);
+                       }
+               }
                switch_event_fire(&event);
        }
 
index 64be6b7f14e99e1af5e277e07baf764ada5ab4a6..4932606ff2f5ae53e04f6ca1482b002d26d6f6ed 100644 (file)
@@ -2219,6 +2219,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_
                        switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
                        switch_xml_set_txt_d(time_tag, tmp);
 
+                       if (!(time_tag = switch_xml_add_child_d(x_times, "bridged_time", t_off++))) {
+                               goto error;
+                       }
+                       switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged);
+                       switch_xml_set_txt_d(time_tag, tmp);
+
                        if (!(time_tag = switch_xml_add_child_d(x_times, "hangup_time", t_off++))) {
                                goto error;
                        }
index 7dc8edfa2cbf10c44c67af9827354bd6acb309ab..0fecc309f705ab68910ad9dd0420c3ebdcb1c31d 100644 (file)
@@ -201,7 +201,9 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
 
        chan_a = switch_core_session_get_channel(session_a);
        chan_b = switch_core_session_get_channel(session_b);
-
+       
+       switch_channel_set_bridge_time(chan_a);
        if ((exec_app = switch_channel_get_variable(chan_a, "bridge_pre_execute_app"))) {
                exec_data = switch_channel_get_variable(chan_a, "bridge_pre_execute_data");
        }
@@ -1067,6 +1069,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_signal_bridge(switch_core_session_t *
                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-Data", switch_core_session_get_uuid(session));
                switch_event_fire(&event);
        }
+
+       switch_channel_set_bridge_time(caller_channel);
+       switch_channel_set_bridge_time(peer_channel);
        
        switch_channel_set_state_flag(caller_channel, CF_RESET);
        switch_channel_set_state_flag(peer_channel, CF_RESET);