[asterisk-commits] murf: branch group/CDRfix5 r77893 - in /team/group/CDRfix5: ./ apps/ funcs/ i...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Aug 1 19:16:14 CDT 2007


Author: murf
Date: Wed Aug  1 19:16:13 2007
New Revision: 77893

URL: http://svn.digium.com/view/asterisk?view=rev&rev=77893
Log:
As per suggestion of Tilghman, we split the read and write of CDR_CONTROL; begin automation of CDR output for non-answer cases

Modified:
    team/group/CDRfix5/CHANGES
    team/group/CDRfix5/apps/app_forkcdr.c
    team/group/CDRfix5/funcs/func_cdr.c
    team/group/CDRfix5/include/asterisk/cdr.h
    team/group/CDRfix5/res/res_features.c

Modified: team/group/CDRfix5/CHANGES
URL: http://svn.digium.com/view/asterisk/team/group/CDRfix5/CHANGES?view=diff&rev=77893&r1=77892&r2=77893
==============================================================================
--- team/group/CDRfix5/CHANGES (original)
+++ team/group/CDRfix5/CHANGES Wed Aug  1 19:16:13 2007
@@ -260,3 +260,32 @@
   * The device state functionality in the Local channel driver has been updated
      to indicate INUSE or NOT_INUSE when a Local channel is being used as opposed
      to just UNKNOWN if the extension exists.
+
+CDR changes
+-----------
+
+  * If you had dialplan that in any way manipulated CDR's, the chances are
+    now good that you will have to rip it out and re-write it!
+  * ForkCDR still exists, but does nothing, and generates a warning. This
+    is not standard obsolescence; it is part of a bug fix that required
+    re-engineering of the system.
+  * By default, Asterisk will only generate a CDR if a bridge was executed.
+    So, no conversation between two endpoints, no CDR. Apps that execute
+    bridges: Dial and Meetme and queue, etc.
+  * the Function CDR_CONTROL() is available to build, set and generate
+    CDR's for non-bridging situations like app and agi calls.
+  * the CDR() function can still be used to set CDR fields before a bridge
+    is formed. It can also be used to set fields in CDRs created by CDR_CONTROL().
+  * Those apps that accepted an arg to update CDR, either still have them (for now),
+    or have had that option removed. The philosophy is a bit different now. A CDR is
+    attached to the channel at the creation of the channel. The channel CDR's start
+    time is set to the time the channel was created. You set up the channel CDR before 
+    executing an app that executes a bridge. The originating
+    channel's CDR is copied into a temporary bridge CDR. The bridge CDR's answer time
+    is set when the bridge begins, and the bridge CDR's end time is set when it closes. 
+    The bridge CDR is then posted to the backend. The channel cdr start time is updated 
+    to the end time of the bridge. Hangup routines are called, and then the channel 
+    is destroyed.
+
+
+    

Modified: team/group/CDRfix5/apps/app_forkcdr.c
URL: http://svn.digium.com/view/asterisk/team/group/CDRfix5/apps/app_forkcdr.c?view=diff&rev=77893&r1=77892&r2=77893
==============================================================================
--- team/group/CDRfix5/apps/app_forkcdr.c (original)
+++ team/group/CDRfix5/apps/app_forkcdr.c Wed Aug  1 19:16:13 2007
@@ -48,7 +48,8 @@
 static char *descrip = 
 "  ForkCDR([options]):  Causes the Call Data Record to fork an additional\n"
 	"cdr record starting from the time of the fork call\n"
-"If the option 'v' is passed all cdr variables will be passed along also.\n";
+"If the option 'v' is passed all cdr variables will be passed along also.\n"
+"NOTE: this app is no longer useful! Refer to the CDR_CONTROL function instead!\n";
 
 
 static int forkcdr_exec(struct ast_channel *chan, void *data)
@@ -63,7 +64,7 @@
 	if (!ast_strlen_zero(data))
 		ast_set2_flag(chan->cdr, strchr(data, 'v'), AST_CDR_FLAG_KEEP_VARS);
 	
-	ast_log(LOG_ERROR,"ForkCDR is obsolesced. It will probably not yield correct results any more. Use CDRstart(), CDRanswer(), and CDRclose() functions instead!\n");
+	ast_log(LOG_ERROR,"ForkCDR is obsolesced. It will probably not yield correct results any more. Use CDR_CONTROL(start/answer/close) function instead!\n");
 	
 
 	return res;

Modified: team/group/CDRfix5/funcs/func_cdr.c
URL: http://svn.digium.com/view/asterisk/team/group/CDRfix5/funcs/func_cdr.c?view=diff&rev=77893&r1=77892&r2=77893
==============================================================================
--- team/group/CDRfix5/funcs/func_cdr.c (original)
+++ team/group/CDRfix5/funcs/func_cdr.c Wed Aug  1 19:16:13 2007
@@ -217,35 +217,22 @@
 };
 
 
-static int function_cdr_control(struct ast_channel *chan, const char *cmd,
+static int function_cdr_control_read(struct ast_channel *chan, const char *cmd,
 								   char *parse, char *buf, size_t len)
 {
 	struct ast_cdr *cdr;
 	
 	AST_DECLARE_APP_ARGS(args,
 			     AST_APP_ARG(action);
-			     AST_APP_ARG(handle);
 	);
 
 	buf[0] = '\0';
 
-	if (ast_strlen_zero(parse)) {
-		ast_log(LOG_ERROR, "CDR_CONTROL requires an action argument, CDR_CONTROL(action[,<handle>])\n");
-		return -1;
-	}
-
 	AST_STANDARD_APP_ARGS(args, parse);
 
-	if (args.argc < 1) {
-		ast_log(LOG_ERROR, "CDR_CONTROL requires an action argument, CDR_CONTROL(action[,<handle>])\n");
-		return -1;
-	}
-	if (strcasecmp(args.action,"start") == 0) {
+	if (args.argc < 1 || strcasecmp(args.action,"start") == 0) {
 		char *handle;
 		
-		if (args.argc > 1)
-			ast_log(LOG_WARNING, "CDR_CONTROL's start action does not need further arguments. Ignoring '%s'.\n", args.handle);
-
 		cdr = calloc(sizeof(struct ast_cdr),1);
 
 		if (!cdr) {
@@ -260,21 +247,51 @@
 	
 		ast_copy_string(buf, handle, len);
 		free(handle);
-	} else if (strcasecmp(args.action,"answer") == 0) {
-		if (args.argc < 2) {
-			ast_log(LOG_ERROR, "CDR_CONTROL's '%s' action requires a 'handle'!\n", args.action);
-			buf[0] = 0;
+	} else if (args.argc == 1 && strcasecmp(args.action,"start") != 0) {
+		ast_log(LOG_ERROR, "CDR_CONTROL does not grok the '%s' action! Command ignored!\n", args.action);
+		ast_copy_string(buf, "BAD.ACTION", len);
+		return -1;
+	}
+	return 0;
+}
+
+static int function_cdr_control_write(struct ast_channel *chan, const char *cmd, char *parse,
+								   const char *value)
+{
+	struct ast_cdr *cdr;
+	
+	AST_DECLARE_APP_ARGS(args,
+			     AST_APP_ARG(handle);
+	);
+
+	if (ast_strlen_zero(parse)) {
+		ast_log(LOG_ERROR, "CDR_CONTROL requires a handle argument, CDR_CONTROL(handle)\n");
+		return -1;
+	}
+
+	AST_STANDARD_APP_ARGS(args, parse);
+
+	if (args.argc < 1) {
+		ast_log(LOG_ERROR, "CDR_CONTROL requires a handle argument, CDR_CONTROL(handle)\n");
+		return -1;
+	}
+	if (strcasecmp(value,"start") == 0) {
+		
+		if (args.argc > 1)
+			ast_log(LOG_WARNING, "CDR_CONTROL does not allow a CDR to be re-started. Command Ignored\n");
+
+	} else if (strcasecmp(value,"answer") == 0) {
+		if (args.argc < 1) {
+			ast_log(LOG_ERROR, "CDR_CONTROL's '%s' action requires a 'handle'!\n", value);
 			return -1;
 		}
 		cdr = (struct ast_cdr*)strtoul(args.handle, NULL, 10);
 		if (!cdr)
 			return -1;
 		ast_cdr_answer(cdr);
-		ast_copy_string(buf, args.handle, len);
-	} else if (strcasecmp(args.action,"close") == 0) {
-		if (args.argc < 2) {
-			ast_log(LOG_ERROR, "CDR_CONTROL's '%s' action requires a 'handle'!\n", args.action);
-			buf[0] = 0;
+	} else if (strcasecmp(value,"close") == 0) {
+		if (args.argc < 1) {
+			ast_log(LOG_ERROR, "CDR_CONTROL's '%s' action requires a 'handle'!\n", value);
 			return -1;
 		}
 		cdr = (struct ast_cdr*)strtoul(args.handle, NULL, 10);
@@ -282,21 +299,17 @@
 			return -1;
 		ast_cdr_end(cdr);
 		ast_cdr_detach(cdr);
-		buf[0] = 0;
-	} else if (strcasecmp(args.action,"abort") == 0) {
-		if (args.argc < 2) {
-			ast_log(LOG_ERROR, "CDR_CONTROL's '%s' action requires a 'handle'!\n", args.action);
-			buf[0] = 0;
+	} else if (strcasecmp(value,"abort") == 0) {
+		if (args.argc < 1) {
+			ast_log(LOG_ERROR, "CDR_CONTROL's '%s' action requires a 'handle'!\n", value);
 			return -1;
 		}
 		cdr = (struct ast_cdr*)strtoul(args.handle, NULL, 10);
 		if (!cdr)
 			return -1;
 		ast_cdr_free(cdr);
-		buf[0] = 0;
 	} else {
-		ast_log(LOG_ERROR, "CDR_CONTROL does not grok the '%s' action! Command ignored!\n", args.action);
-		ast_copy_string(buf, "BAD.ACTION", len);
+		ast_log(LOG_ERROR, "CDR_CONTROL does not grok the '%s' action! Command ignored!\n", value);
 		return -1;
 	}
 	return 0;
@@ -305,42 +318,44 @@
 static struct ast_custom_function cdr_control_function = {
 	.name = "CDR_CONTROL",
 	.synopsis = "A single function for generating your own CDR's from the dialplan",
-	.syntax = "CDR_CONTROL(action[|handle])",
+	.syntax = "CDR_CONTROL([handle])",
 	.desc =
 "This function is used to create, set times, post, or destroy your own custom CDR's\n"
 "from the dialplan. These CDR's are not stored on the channel as traditional CDR's are.\n"
 "You can open as many CDR's as you wish simultaneously. You have complete control of the\n"
-"contents of the CDR's, via the CDR() function, supplying the 'handle' in the optional third arg.\n"
-"The 'action' argument can be one of:\n"
-"    start     (allocate a CDR, and pass back a 'handle' to it)\n"
+"contents of the CDR's, via the CDR() function, supplying the 'handle' in the optional 3rd arg.\n"
+"To create a CDR, read from this function; The handle argument should be 'start' or empty.\n"
+"for example:  Set(someval=${CDR_CONTROL()}); this will create a CDR, and set it's start time.\n"
+"To set the answer time, or to set the end time and post the CDR, set the function using the\n"
+"value returned from starting a CDR. Use the function in this manner: Set(CDR_CONTROL(${someval})=action)\n"
+"where 'someval' contains the result of reading (starting) CDR_CONTROL, as in the previous example,\n"
+"and the 'action' value can be one of:\n"
 "    answer    (set the answer time to the current time in the CDR associated with the 'handle')\n"
 "    close     (set the end time for the CDR, and post and detach it)\n"
 "    abort     (oops, don't need this CDR after all, free and destroy it without posting)\n"
-"If you specify any action other than 'start', you must also supply a handle.\n"
-"The start action returns a new handle. The answer action returns the same handle it was given.\n"
-"The close and abort actions return an empty string.\n"
-"Every 'start' action should be matched at some point with a 'close' or 'abort' action\n"
+"Every CDR created with CDR_CONTROL() should be matched at some point with a 'close' or 'abort' action\n"
 "to avoid memory leaks.\n"
 "\n"
 "This function can be very useful for:\n"
 " 1. Generating CDR's for recording time spent in an application or AGI script.\n"
-" 2. Generating CDR's to record unanswered calls, or calls terminated before they are answered.\n"
+" 2. Or any other type of event not covered well by the default CDR mechanisms.\n"
 "\n"
 "Example: (in AEL)\n"
 "context test\n"
 "{\n"
 "        5 => {\n"
 "                Set(mycdr=${CDR_CONTROL(start)});\n"
-"                NoOp(CDR_CONTROL(answer) says: ${CDR_CONTROL(answer,${mycdr})} );\n"
-"                Set(CDR(lastapp||${mycdr})=Record+BackGround);\n"
-"                Set(CDR(lastdata||${mycdr})=whoknows);\n"
+"                Set(CDR_CONTROL(${mycdr})=answer);\n"
+"                Set(CDR(lastapp,,${mycdr})=Record+BackGround);\n"
+"                Set(CDR(lastdata,,${mycdr})=whoknows);\n"
 "                Record(recording:wav);\n"
 "                Background(recording);\n"
-"                NoOp(CDR_CONTROL(close) says: ${CDR_CONTROL(close,${mycdr})} );\n"
+"                Set(CDR_CONTROL(${mycdr})=close);\n"
 "        }\n"
 "}\n",
 	
-	.read = function_cdr_control
+	.read = function_cdr_control_read,
+	.write = function_cdr_control_write,
 };
 
 

Modified: team/group/CDRfix5/include/asterisk/cdr.h
URL: http://svn.digium.com/view/asterisk/team/group/CDRfix5/include/asterisk/cdr.h?view=diff&rev=77893&r1=77892&r2=77893
==============================================================================
--- team/group/CDRfix5/include/asterisk/cdr.h (original)
+++ team/group/CDRfix5/include/asterisk/cdr.h Wed Aug  1 19:16:13 2007
@@ -24,12 +24,12 @@
 #define _ASTERISK_CDR_H
 
 #include <sys/time.h>
-#define AST_CDR_FLAG_KEEP_VARS			(1 << 0)
+#define AST_CDR_FLAG_KEEP_VARS		(1 << 0)
 #define AST_CDR_FLAG_POSTED			(1 << 1)
-#define AST_CDR_FLAG_LOCKED			(1 << 2)
+#define AST_CDR_FLAG_BRIDGED		(1 << 2)
 #define AST_CDR_FLAG_CHILD			(1 << 3)
-#define AST_CDR_FLAG_POST_DISABLED		(1 << 4)
-#define AST_CDR_FLAG_MAIN		(1 << 5)
+#define AST_CDR_FLAG_POST_DISABLED	(1 << 4)
+#define AST_CDR_FLAG_MAIN			(1 << 5)
 
 #define AST_CDR_NULL                0
 #define AST_CDR_FAILED				(1 << 0)
@@ -40,10 +40,10 @@
 /*! AMA Flags */
 #define AST_CDR_OMIT				(1)
 #define AST_CDR_BILLING				(2)
-#define AST_CDR_DOCUMENTATION			(3)
+#define AST_CDR_DOCUMENTATION		(3)
 
 #define AST_MAX_USER_FIELD			256
-#define AST_MAX_ACCOUNT_CODE			20
+#define AST_MAX_ACCOUNT_CODE		20
 
 /* Include channel.h after relevant declarations it will need */
 #include "asterisk/channel.h"

Modified: team/group/CDRfix5/res/res_features.c
URL: http://svn.digium.com/view/asterisk/team/group/CDRfix5/res/res_features.c?view=diff&rev=77893&r1=77892&r2=77893
==============================================================================
--- team/group/CDRfix5/res/res_features.c (original)
+++ team/group/CDRfix5/res/res_features.c Wed Aug  1 19:16:13 2007
@@ -1714,6 +1714,10 @@
 			}
 		}
 		ast_cdr_answer(bridge_cdr);
+		ast_cdr_answer(chan->cdr); /* for the sake of cli status checks */
+		ast_set_flag(chan->cdr, AST_CDR_FLAG_BRIDGED);
+		if (peer->cdr)
+			ast_set_flag(peer->cdr, AST_CDR_FLAG_BRIDGED);
 	}
 	
 	




More information about the asterisk-commits mailing list