[Freeswitch-svn] [commit] r5779 - in freeswitch/trunk/src: . include mod/applications/mod_fifo

Freeswitch SVN anthm at freeswitch.org
Tue Oct 2 15:58:07 EDT 2007


Author: anthm
Date: Tue Oct  2 15:58:06 2007
New Revision: 5779

Modified:
   freeswitch/trunk/src/include/switch_ivr.h
   freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c
   freeswitch/trunk/src/switch_channel.c
   freeswitch/trunk/src/switch_ivr.c

Log:
improve mod-fifo

Modified: freeswitch/trunk/src/include/switch_ivr.h
==============================================================================
--- freeswitch/trunk/src/include/switch_ivr.h	(original)
+++ freeswitch/trunk/src/include/switch_ivr.h	Tue Oct  2 15:58:06 2007
@@ -89,6 +89,8 @@
   \note on success the xml object must be freed
 */
 SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_t *session, switch_xml_t * xml_cdr);
+SWITCH_DECLARE(int) switch_ivr_set_xml_profile_data(switch_xml_t xml, switch_caller_profile_t *caller_profile, int off);
+SWITCH_DECLARE(int) switch_ivr_set_xml_chan_vars(switch_xml_t xml, switch_channel_t *channel, int off);
 
 /*!
   \brief Parse command from an event

Modified: freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c	Tue Oct  2 15:58:06 2007
@@ -34,6 +34,8 @@
 SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load);
 SWITCH_MODULE_DEFINITION(mod_fifo, mod_fifo_load, mod_fifo_shutdown, NULL);
 
+#define FIFO_EVENT "fifo::info"
+
 
 
 static switch_status_t on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
@@ -79,20 +81,41 @@
 
 static struct {
     switch_hash_t *fifo_hash;
+    switch_mutex_t *mutex;
     switch_memory_pool_t *pool;
 } globals;
 
+
+struct fifo_node {
+    char *name;
+    switch_mutex_t *mutex;
+    switch_queue_t *fifo;
+    switch_hash_t *caller_hash;
+    switch_hash_t *consumer_hash;
+    int caller_count;
+    int consumer_count;
+};
+
+typedef struct fifo_node fifo_node_t;
+
 #define FIFO_DESC "Fifo for stacking parked calls."
 #define FIFO_USAGE "<fifo name> [in [<announce file>|undef] [<music file>|undef] | out [wait|nowait] [<announce file>|undef] [<music file>|undef]]"
 SWITCH_STANDARD_APP(fifo_function)
 {
     int argc;
     char *mydata = NULL, *argv[5] = { 0 };
-    switch_queue_t *fifo;
+    fifo_node_t *node;
     switch_channel_t *channel;
     int nowait = 0;
     char *moh = NULL;
     char *announce = NULL;
+    switch_event_t *event = NULL;
+    char date[80] = "";
+    switch_time_exp_t tm;
+    switch_time_t ts = switch_time_now();
+    switch_size_t retsize;
+
+
 
 
     if (switch_strlen_zero(data)) {
@@ -107,11 +130,19 @@
         return;
     }
 
-    if (!(fifo = switch_core_hash_find(globals.fifo_hash, argv[0]))) {
-        switch_queue_create(&fifo, SWITCH_CORE_QUEUE_LEN, globals.pool);
-        assert(fifo);
-        switch_core_hash_insert(globals.fifo_hash, argv[0], fifo);
+    switch_mutex_lock(globals.mutex);
+    if (!(node = switch_core_hash_find(globals.fifo_hash, argv[0]))) {
+        node = switch_core_alloc(globals.pool, sizeof(*node));
+        node->name = switch_core_strdup(globals.pool, argv[0]);
+        switch_queue_create(&node->fifo, SWITCH_CORE_QUEUE_LEN, globals.pool);
+        switch_core_hash_init(&node->caller_hash, globals.pool);
+        switch_core_hash_init(&node->consumer_hash, globals.pool);
+        assert(node->fifo);
+        switch_mutex_init(&node->mutex, SWITCH_MUTEX_NESTED, globals.pool);
+        switch_core_hash_insert(globals.fifo_hash, argv[0], node);
     }
+    switch_mutex_unlock(globals.mutex);
+
 
     channel = switch_core_session_get_channel(session);
     moh = switch_channel_get_variable(channel, "fifo_music");
@@ -129,7 +160,7 @@
         if (argc > 2) {
             announce = argv[2];
         }
-
+        
         if (argc > 3) {
             moh = argv[3];
         }
@@ -143,10 +174,29 @@
         }
         
         switch_channel_set_flag(channel, CF_TAGGED);
+
+        switch_mutex_lock(node->mutex);
+        node->caller_count++;
+        switch_core_hash_insert(node->caller_hash, uuid, session);
+        switch_queue_push(node->fifo, uuid);
+        switch_mutex_unlock(node->mutex);
+
+        switch_time_exp_lt(&tm, ts);
+        switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
+        switch_channel_set_variable(channel, "fifo_status", "WAITING");
+        switch_channel_set_variable(channel, "fifo_timestamp", date);
         
-        switch_queue_push(fifo, uuid);
+		if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+			switch_channel_event_set_data(channel, event);
+            switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
+            switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "push");
+			switch_event_fire(&event);
+		}
+
         switch_ivr_park(session, NULL);
-        
+
+
+
         if (switch_channel_ready(channel)) {
             if (announce) {
                 switch_ivr_play_file(session, NULL, announce, NULL);
@@ -156,7 +206,24 @@
         switch_channel_clear_flag(channel, CF_TAGGED);
 
         if (switch_channel_ready(channel)) {
-            switch_channel_set_state(channel, CS_HIBERNATE);
+            switch_channel_set_state(channel, CS_HIBERNATE);            
+        } else {
+
+            switch_time_exp_lt(&tm, ts);
+            switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
+            switch_channel_set_variable(channel, "fifo_status", "ABORTED");
+            switch_channel_set_variable(channel, "fifo_timestamp", date);
+            
+            if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+                switch_channel_event_set_data(channel, event);
+                switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
+                switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "abort");
+                switch_event_fire(&event);
+            }
+            switch_mutex_lock(node->mutex);
+            node->caller_count--;
+            switch_core_hash_delete(node->caller_hash, uuid);
+            switch_mutex_unlock(node->mutex);
         }
         
         return;
@@ -179,31 +246,50 @@
         
         check_string(announce);
         check_string(moh);
-                            
+        
         if (!nowait) {
+            switch_mutex_lock(node->mutex);
+            node->consumer_count++;
+            switch_core_hash_insert(node->consumer_hash, switch_core_session_get_uuid(session), session);
+            switch_mutex_unlock(node->mutex);
             switch_channel_answer(channel);
         }
         
 
-        for (;;) {
+        if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+            switch_channel_event_set_data(channel, event);
+            switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
+            switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_start");
+            switch_event_fire(&event);
+        }
+
+
+        switch_time_exp_lt(&tm, ts);
+        switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
+        switch_channel_set_variable(channel, "fifo_status", "WAITING");
+        switch_channel_set_variable(channel, "fifo_timestamp", date);
+
+
+
+        while(switch_channel_ready(channel)) {
             if (moh) {
                 args.read_frame_callback = read_frame_callback;
-                args.user_data = fifo;
+                args.user_data = node->fifo;
                 switch_ivr_play_file(session, NULL, moh, &args);
             }
 
-            if (switch_queue_trypop(fifo, &pop) != SWITCH_STATUS_SUCCESS) {
+            if (switch_queue_trypop(node->fifo, &pop) != SWITCH_STATUS_SUCCESS) {
                 if (nowait) {
-                    return;
+                    break;
                 }
                 status = switch_core_session_read_frame(session, &read_frame, -1, 0);
                 if (!SWITCH_READ_ACCEPTABLE(status)) {
-                    return;
+                    break;
                 }
                 continue;
             }
             if (!pop) {
-                return;
+                break;
             }
 
             uuid = (char *) pop;
@@ -211,20 +297,40 @@
             if ((other_session = switch_core_session_locate(uuid))) {
                 switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
                 switch_caller_profile_t *cloned_profile;
+
+
+                if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+                    switch_channel_event_set_data(other_channel, event);
+                    switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
+                    switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "caller_pop");
+                    switch_event_fire(&event);
+                }
+
+                if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+                    switch_channel_event_set_data(channel, event);
+                    switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
+                    switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_pop");
+                    switch_event_fire(&event);
+                }
+
+
                 
                 if (announce) {
                     switch_ivr_play_file(session, NULL, announce, NULL);
                 } else {
                     switch_ivr_sleep(session, 500);
                 }
-                switch_channel_clear_flag(other_channel, CF_CONTROLLED);
-                switch_channel_clear_flag(other_channel, CF_BROADCAST);
-                switch_channel_set_flag(other_channel, CF_BREAK);
-                switch_core_session_kill_channel(other_session, SWITCH_SIG_BREAK);
-                while (switch_channel_test_flag(other_channel, CF_TAGGED)) {
-                    status = switch_core_session_read_frame(session, &read_frame, -1, 0);
-                    if (!SWITCH_READ_ACCEPTABLE(status)) {
-                        break;
+
+                if (switch_channel_test_flag(other_channel, CF_TAGGED)) {
+                    switch_channel_clear_flag(other_channel, CF_CONTROLLED);
+                    switch_channel_clear_flag(other_channel, CF_BROADCAST);
+                    switch_channel_set_flag(other_channel, CF_BREAK);
+                    switch_core_session_kill_channel(other_session, SWITCH_SIG_BREAK);
+                    while (switch_channel_test_flag(other_channel, CF_TAGGED)) {
+                        status = switch_core_session_read_frame(session, &read_frame, -1, 0);
+                        if (!SWITCH_READ_ACCEPTABLE(status)) {
+                            break;
+                        }
                     }
                 }
 
@@ -238,7 +344,29 @@
                 assert(cloned_profile->next == NULL);
                 switch_channel_set_originatee_caller_profile(channel, cloned_profile);
 				
+                switch_time_exp_lt(&tm, ts);
+                switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
+                switch_channel_set_variable(channel, "fifo_status", "TALKING");
+                switch_channel_set_variable(channel, "fifo_target", uuid);
+                switch_channel_set_variable(channel, "fifo_timestamp", date);
+                
+                switch_channel_set_variable(other_channel, "fifo_status", "TALKING");
+                switch_channel_set_variable(other_channel, "fifo_timestamp", date);
+                switch_channel_set_variable(other_channel, "fifo_target", switch_core_session_get_uuid(session));
                 switch_ivr_multi_threaded_bridge(session, other_session, on_dtmf, other_session, session);
+
+                switch_time_exp_lt(&tm, ts);
+                switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
+                switch_channel_set_variable(channel, "fifo_status", "WAITING");
+                switch_channel_set_variable(channel, "fifo_timestamp", date);
+
+                switch_channel_set_variable(other_channel, "fifo_status", "DONE");
+                switch_channel_set_variable(other_channel, "fifo_timestamp", date);
+                
+                switch_mutex_lock(node->mutex);
+                node->caller_count--;
+                switch_core_hash_delete(node->caller_hash, uuid);
+                switch_mutex_unlock(node->mutex);
                 switch_core_session_rwunlock(other_session);
                 if (nowait) {
                     done = 1;
@@ -251,23 +379,206 @@
                 break;
             }
         }
+
+
+        if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+            switch_channel_event_set_data(channel, event);
+            switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
+            switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_stop");
+            switch_event_fire(&event);
+        }
+
+        if (!nowait) {
+            switch_mutex_lock(node->mutex);
+            switch_core_hash_delete(node->consumer_hash, switch_core_session_get_uuid(session));
+            node->consumer_count--;
+            switch_mutex_unlock(node->mutex);
+        }
+        
     } else {
         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "USAGE %s\n", FIFO_USAGE);
     }
 
 }
 
+static int xml_hash(switch_xml_t xml, switch_hash_t *hash, char *container, char *tag, int cc_off, int verbose)
+{
+    switch_xml_t x_tmp, x_caller, x_cp, variables;
+    switch_hash_index_t *hi;
+    switch_core_session_t *session;
+    switch_channel_t *channel;
+    void *val;
+    const void *var;
+
+    x_tmp = switch_xml_add_child_d(xml, container, cc_off++);
+    assert(x_tmp);
+
+    for (hi = switch_hash_first(NULL, hash); hi; hi = switch_hash_next(hi)) {
+        int c_off = 0, d_off = 0;
+        char *status;
+        char *ts;
+
+        switch_hash_this(hi, &var, NULL, &val);
+        session = (switch_core_session_t *) val;
+        channel = switch_core_session_get_channel(session);
+        x_caller = switch_xml_add_child_d(x_tmp, tag, c_off++);
+        assert(x_caller);
+        
+        switch_xml_set_attr_d(x_caller, "uuid", switch_core_session_get_uuid(session));
+
+        if ((status = switch_channel_get_variable(channel, "fifo_status"))) {
+            switch_xml_set_attr_d(x_caller, "status", status);
+        }
+
+        if ((ts = switch_channel_get_variable(channel, "fifo_timestamp"))) {
+            switch_xml_set_attr_d(x_caller, "timestamp", ts);
+        }
+
+        if ((ts = switch_channel_get_variable(channel, "fifo_target"))) {
+            switch_xml_set_attr_d(x_caller, "target", ts);
+        }
+        
+		if (!(x_cp = switch_xml_add_child_d(x_caller, "caller_profile", d_off++))) {
+            abort();
+		}
+        if (verbose) {
+            d_off += switch_ivr_set_xml_profile_data(x_cp, switch_channel_get_caller_profile(channel), d_off);
+        
+            if (!(variables = switch_xml_add_child_d(x_caller, "variables", c_off++))) {
+                abort();
+            }
+        
+            switch_ivr_set_xml_chan_vars(variables, channel, c_off);
+        }
+        
+    }
+
+    return cc_off;
+}
+
+static void list_node(fifo_node_t *node, switch_xml_t x_report, int *off, int verbose)
+{
+
+    switch_xml_t x_fifo;
+    int cc_off = 0;
+    char tmp[35];
+
+    x_fifo = switch_xml_add_child_d(x_report, "fifo", (*off)++);;
+    assert(x_fifo);
+
+    switch_xml_set_attr_d(x_fifo, "name", node->name);
+    snprintf(tmp, sizeof(tmp), "%d", node->consumer_count);
+    switch_xml_set_attr_d(x_fifo, "consumer_count", tmp);
+    snprintf(tmp, sizeof(tmp), "%d", node->caller_count);
+    switch_xml_set_attr_d(x_fifo, "caller_count", tmp);
+    
+    cc_off = xml_hash(x_fifo, node->caller_hash, "callers", "caller", cc_off, verbose);
+    cc_off = xml_hash(x_fifo, node->consumer_hash, "consumers", "consumer", cc_off, verbose);
+
+}
+
+#define FIFO_API_SYNTAX "count <fifo name>"
+SWITCH_STANDARD_API(fifo_api_function)
+{
+    int len = 0;
+    fifo_node_t *node;
+    char *data;
+    int argc = 0;
+    char *argv[5] = { 0 };
+    switch_hash_index_t *hi;
+    void *val;
+    const void *var;
+    int x = 0, verbose = 0;
+
+    if (!switch_strlen_zero(cmd)) {
+        data = strdup(cmd);
+        assert(data);
+    }
+    
+    if (switch_strlen_zero(cmd) || (argc = switch_separate_string(data, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) < 1) {
+        stream->write_function(stream, "%s\n", FIFO_API_SYNTAX);
+        return SWITCH_STATUS_SUCCESS;
+    }
+
+    switch_mutex_lock(globals.mutex);
+    verbose = !strcasecmp(argv[0], "list_verbose");
+
+    if (!strcasecmp(argv[0], "list") || verbose) {    
+        char *xml_text = NULL;
+        switch_xml_t x_report = switch_xml_new("fifo_report");
+        assert(x_report);
+
+        if (argc < 2) {
+            for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
+                switch_hash_this(hi, &var, NULL, &val);
+                node = (fifo_node_t *) val;
+                switch_mutex_lock(node->mutex);
+                list_node(node, x_report, &x, verbose);
+                switch_mutex_unlock(node->mutex);
+            }
+        } else {
+            if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
+                switch_mutex_lock(node->mutex);
+                list_node(node, x_report, &x, verbose);
+                switch_mutex_unlock(node->mutex);
+            }
+        }
+        xml_text = switch_xml_toxml(x_report);
+        assert(xml_text);
+        stream->write_function(stream, "%s\n", xml_text);
+        switch_xml_free(x_report);
+        switch_safe_free(xml_text);
+        
+    } else if (!strcasecmp(argv[0], "count")) {
+        if (argc < 2) {
+            for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
+                switch_hash_this(hi, &var, NULL, &val);
+                node = (fifo_node_t *) val;
+                len = switch_queue_size(node->fifo);
+                switch_mutex_lock(node->mutex);
+                stream->write_function(stream, "%s:%d:%d:%d\n", (char *)var, node->consumer_count, node->caller_count, len);
+                switch_mutex_unlock(node->mutex);
+                x++;
+            }
+            
+            if (!x) {
+                stream->write_function(stream, "none\n");
+            }
+        } else {
+            if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
+                len = switch_queue_size(node->fifo);
+            }
+            switch_mutex_lock(node->mutex);
+            stream->write_function(stream, "%s:%d:%d:%d\n", argv[1], node->consumer_count, node->caller_count, len);
+            switch_mutex_unlock(node->mutex);
+        }
+    }
+
+    switch_mutex_unlock(globals.mutex);
+    return SWITCH_STATUS_SUCCESS;
+}
+
+
 SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load)
 {
 	switch_application_interface_t *app_interface;
+    switch_api_interface_t *commands_api_interface;
+
+
+	/* create/register custom event message type */
+	if (switch_event_reserve_subclass(FIFO_EVENT) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!", FIFO_EVENT);
+		return SWITCH_STATUS_TERM;
+	}
 
     switch_core_new_memory_pool(&globals.pool);
     switch_core_hash_init(&globals.fifo_hash, globals.pool);
+    switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
 
 	/* connect my internal structure to the blank pointer passed to me */
 	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
 	SWITCH_ADD_APP(app_interface, "fifo", "Park with FIFO", FIFO_DESC, fifo_function, FIFO_USAGE, SAF_NONE);
-
+    SWITCH_ADD_API(commands_api_interface, "fifo", "Return data about a fifo", fifo_api_function, FIFO_API_SYNTAX);
 
 	return SWITCH_STATUS_SUCCESS;
 }
@@ -279,16 +590,19 @@
 {
     switch_hash_index_t *hi;
     void *val, *pop;
-    switch_queue_t *fifo;
-
+    fifo_node_t *node;
+    switch_mutex_lock(globals.mutex);
     /* Cleanup*/
     for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
         switch_hash_this(hi, NULL, NULL, &val);
-        fifo = (switch_queue_t *) val;
-        while (switch_queue_trypop(fifo, &pop) == SWITCH_STATUS_SUCCESS) {
+        node = (fifo_node_t *) val;
+        while (switch_queue_trypop(node->fifo, &pop) == SWITCH_STATUS_SUCCESS) {
             free(pop);
         }
+        switch_core_hash_destroy(&node->caller_hash);
+        switch_core_hash_destroy(&node->consumer_hash);
     }
+    switch_mutex_unlock(globals.mutex);
     switch_core_hash_destroy(&globals.fifo_hash);
     switch_core_destroy_memory_pool(&globals.pool);
 	return SWITCH_STATUS_SUCCESS;

Modified: freeswitch/trunk/src/switch_channel.c
==============================================================================
--- freeswitch/trunk/src/switch_channel.c	(original)
+++ freeswitch/trunk/src/switch_channel.c	Tue Oct  2 15:58:06 2007
@@ -404,11 +404,10 @@
 	
 	if (!switch_strlen_zero(varname)) {
 		switch_mutex_lock(channel->profile_mutex);
+		switch_event_del_header(channel->variables, varname);
 		if (value) {
 			switch_event_add_header(channel->variables, SWITCH_STACK_BOTTOM, varname, "%s", value);
-		} else {
-			switch_event_del_header(channel->variables, varname);
-		}
+		} 
 		switch_mutex_unlock(channel->profile_mutex);
 		return SWITCH_STATUS_SUCCESS;
 	}

Modified: freeswitch/trunk/src/switch_ivr.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr.c	(original)
+++ freeswitch/trunk/src/switch_ivr.c	Tue Oct  2 15:58:06 2007
@@ -1206,7 +1206,7 @@
 	return status;
 }
 
-static int set_profile_data(switch_xml_t xml, switch_caller_profile_t *caller_profile, int off)
+SWITCH_DECLARE(int) switch_ivr_set_xml_profile_data(switch_xml_t xml, switch_caller_profile_t *caller_profile, int off)
 {
 	switch_xml_t param;
 
@@ -1278,14 +1278,43 @@
 	return off;
 }
 
+SWITCH_DECLARE(int) switch_ivr_set_xml_chan_vars(switch_xml_t xml, switch_channel_t *channel, int off)
+{
+	switch_event_header_t *hi;
+	switch_xml_t variable;
+
+	if ((hi = switch_channel_variable_first(channel))) {
+		for (; hi; hi = hi->next) {
+			char *vvar = hi->name;
+			char *vval = hi->value;
+			if (vvar && vval) {
+				if ((variable = switch_xml_add_child_d(xml, (char *) vvar, off++))) {
+					char *data;
+					char *value = (char *) vval;
+					switch_size_t dlen = strlen(value) * 3;
+					
+					if ((data = malloc(dlen))) {
+						memset(data, 0, dlen);
+						switch_url_encode(value, data, dlen);
+						switch_xml_set_txt_d(variable, data);
+						free(data);
+					}
+				}
+			}
+		}
+		switch_channel_variable_last(channel);
+	}
+
+	return off;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_t *session, switch_xml_t * xml_cdr)
 {
 	switch_channel_t *channel;
 	switch_caller_profile_t *caller_profile;
-	switch_xml_t variable, variables, cdr, x_main_cp, x_caller_profile, x_caller_extension, x_times, time_tag, 
+	switch_xml_t variables, cdr, x_main_cp, x_caller_profile, x_caller_extension, x_times, time_tag, 
 		x_application, x_callflow, x_inner_extension, x_apps, x_o;
 	switch_app_log_t *app_log;
-	switch_event_header_t *hi;
 	char tmp[512];
 	int cdr_off = 0, v_off = 0;
 
@@ -1318,27 +1347,8 @@
 		}
 	}
 
-
-	if ((hi = switch_channel_variable_first(channel))) {
-		for (; hi; hi = hi->next) {
-			char *vvar = hi->name;
-			char *vval = hi->value;
-			if (vvar && vval) {
-				if ((variable = switch_xml_add_child_d(variables, (char *) vvar, v_off++))) {
-					char *data;
-					char *value = (char *) vval;
-					switch_size_t dlen = strlen(value) * 3;
-					
-					if ((data = switch_core_session_alloc(session, dlen))) {
-						switch_url_encode(value, data, dlen);
-						switch_xml_set_txt_d(variable, data);
-					}
-				}
-			}
-		}
-		switch_channel_variable_last(channel);
-	}
-
+	switch_ivr_set_xml_chan_vars(variables, channel, v_off);
+	
 	caller_profile = switch_channel_get_caller_profile(channel);
 
 	while (caller_profile) {
@@ -1419,7 +1429,7 @@
 			goto error;
 		}
 
-		cp_off += set_profile_data(x_main_cp, caller_profile, 0);
+		cp_off += switch_ivr_set_xml_profile_data(x_main_cp, caller_profile, 0);
 
 		if (caller_profile->originator_caller_profile) {
 			switch_caller_profile_t *cp = NULL;
@@ -1432,7 +1442,7 @@
 				if (!(x_caller_profile = switch_xml_add_child_d(x_o, "originator_caller_profile", off++))) {
 					goto error;
 				}
-				set_profile_data(x_caller_profile, cp, 0);
+				switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0);
 			}
 		}
 
@@ -1446,7 +1456,7 @@
 				if (!(x_caller_profile = switch_xml_add_child_d(x_o, "originatee_caller_profile", off++))) {
 					goto error;
 				}
-				set_profile_data(x_caller_profile, caller_profile->originatee_caller_profile, 0);
+				switch_ivr_set_xml_profile_data(x_caller_profile, caller_profile->originatee_caller_profile, 0);
 			}
 		}
 



More information about the Freeswitch-svn mailing list