[asterisk-commits] murf: branch murf/CDRfix5 r69131 - /team/murf/CDRfix5/funcs/func_cdr.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Jun 13 11:24:12 MST 2007


Author: murf
Date: Wed Jun 13 13:24:12 2007
New Revision: 69131

URL: http://svn.digium.com/view/asterisk?view=rev&rev=69131
Log:
Created the funcs CDRstart, CDRanswer, and CDRclose. They work. Modded CDR to take 3rd arg of handle, to set all cdr vals

Modified:
    team/murf/CDRfix5/funcs/func_cdr.c

Modified: team/murf/CDRfix5/funcs/func_cdr.c
URL: http://svn.digium.com/view/asterisk/team/murf/CDRfix5/funcs/func_cdr.c?view=diff&rev=69131&r1=69130&r2=69131
==============================================================================
--- team/murf/CDRfix5/funcs/func_cdr.c (original)
+++ team/murf/CDRfix5/funcs/func_cdr.c Wed Jun 13 13:24:12 2007
@@ -63,6 +63,7 @@
 	AST_DECLARE_APP_ARGS(args,
 			     AST_APP_ARG(variable);
 			     AST_APP_ARG(options);
+			     AST_APP_ARG(handle);
 	);
 
 	if (ast_strlen_zero(parse))
@@ -90,10 +91,12 @@
 static int cdr_write(struct ast_channel *chan, const char *cmd, char *parse,
 		     const char *value)
 {
+	struct ast_cdr *cdr = 0;
 	struct ast_flags flags = { 0 };
 	AST_DECLARE_APP_ARGS(args,
 			     AST_APP_ARG(variable);
 			     AST_APP_ARG(options);
+			     AST_APP_ARG(handle);
 	);
 
 	if (ast_strlen_zero(parse) || !value || !chan)
@@ -104,24 +107,78 @@
 	if (!ast_strlen_zero(args.options))
 		ast_app_parse_options(cdr_func_options, &flags, NULL, args.options);
 
-	if (!strcasecmp(args.variable, "accountcode"))
-		ast_cdr_setaccount(chan, value);
-	else if (!strcasecmp(args.variable, "userfield"))
-		ast_cdr_setuserfield(chan, value);
-	else if (!strcasecmp(args.variable, "amaflags"))
-		ast_cdr_setamaflags(chan, value);
-	else if (chan->cdr)
-		ast_cdr_setvar(chan->cdr, args.variable, value, ast_test_flag(&flags, OPT_RECURSIVE));
+	if (ast_strlen_zero(args.handle)) {
+		if (!strcasecmp(args.variable, "accountcode"))
+			ast_cdr_setaccount(chan, value);
+		else if (!strcasecmp(args.variable, "userfield"))
+			ast_cdr_setuserfield(chan, value);
+		else if (!strcasecmp(args.variable, "amaflags"))
+			ast_cdr_setamaflags(chan, value);
+		else if (chan->cdr)
+			ast_cdr_setvar(chan->cdr, args.variable, value, ast_test_flag(&flags, OPT_RECURSIVE));
 		/* No need to worry about the u flag, as all fields for which setting
 		 * 'u' would do anything are marked as readonly. */
-
-	return 0;
+		
+		return 0;
+	} else {
+		cdr = (struct ast_cdr*)strtoul(args.handle, NULL, 10);
+
+		if (!cdr) /* safety valve */
+			return 0;
+	
+		if (!strcasecmp(args.variable, "accountcode"))
+			ast_copy_string(cdr->accountcode, value, sizeof(cdr->accountcode));
+		else if (!strcasecmp(args.variable, "userfield"))
+			ast_copy_string(cdr->userfield, value, sizeof(cdr->userfield));
+		else if (!strcasecmp(args.variable, "amaflags"))
+		{
+			if (atoi(value) > 0 )
+				cdr->amaflags = atoi(value);
+			else
+				cdr->amaflags = ast_cdr_amaflags2int(value);
+		} else if (!strcasecmp(args.variable, "clid"))
+			ast_copy_string(cdr->clid, value, sizeof(cdr->clid));
+		else if (!strcasecmp(args.variable, "src"))
+			ast_copy_string(cdr->src, value, sizeof(cdr->src));
+		else if (!strcasecmp(args.variable, "dst"))
+			ast_copy_string(cdr->dst, value, sizeof(cdr->dst));
+		else if (!strcasecmp(args.variable, "dcontext"))
+			ast_copy_string(cdr->dcontext, value, sizeof(cdr->dcontext));
+		else if (!strcasecmp(args.variable, "channel"))
+			ast_copy_string(cdr->channel, value, sizeof(cdr->channel));
+		else if (!strcasecmp(args.variable, "dstchannel"))
+			ast_copy_string(cdr->dstchannel, value, sizeof(cdr->dstchannel));
+		else if (!strcasecmp(args.variable, "lastapp"))
+			ast_copy_string(cdr->lastapp, value, sizeof(cdr->lastapp));
+		else if (!strcasecmp(args.variable, "lastdata"))
+			ast_copy_string(cdr->lastdata, value, sizeof(cdr->lastdata));
+		else if (!strcasecmp(args.variable, "disposition")) {
+			if (atoi(value) > 0)
+				cdr->disposition = atoi(value);
+			else {
+				if (strcasecmp(value,"NO ANSWER") == 0)
+					cdr->disposition = AST_CDR_NOANSWER;
+				else if (strcasecmp(value,"BUSY") == 0)
+					cdr->disposition = AST_CDR_BUSY;
+				else if (strcasecmp(value,"ANSWERED") == 0)
+					cdr->disposition = AST_CDR_ANSWERED;
+				else if (strcasecmp(value,"FAILED") == 0)
+					cdr->disposition = AST_CDR_FAILED;
+				else if (strcasecmp(value,"NULL") == 0)
+					cdr->disposition = AST_CDR_NULL;
+			}
+		} else if (!strcasecmp(args.variable, "uniqueid"))
+			ast_copy_string(cdr->uniqueid, value, sizeof(cdr->uniqueid));
+		else
+			ast_cdr_setvar(cdr, args.variable, value, ast_test_flag(&flags, OPT_RECURSIVE));
+		return 0;
+	}
 }
 
 static struct ast_custom_function cdr_function = {
 	.name = "CDR",
 	.synopsis = "Gets or sets a CDR variable",
-	.syntax = "CDR(<name>[|options])",
+	.syntax = "CDR(<name>[|options[|handle]])",
 	.read = cdr_read,
 	.write = cdr_write,
 	.desc =
@@ -132,37 +189,179 @@
 "  values, when the 'u' option is passed, but formatted as YYYY-MM-DD HH:MM:SS\n"
 "  otherwise.  Similarly, disposition and amaflags will return their raw\n"
 "  integral values.\n"
-"  Here is a list of all the available cdr field names:\n"
-"    clid          lastdata       disposition\n"
-"    src           start          amaflags\n"
-"    dst           answer         accountcode\n"
-"    dcontext      end            uniqueid\n"
-"    dstchannel    duration       userfield\n"
-"    lastapp       billsec        channel\n"
-"  All of the above variables are read-only, except for accountcode,\n"
-"  userfield, and amaflags. You may, however,  supply\n"
-"  a name not on the above list, and create your own\n"
-"  variable, whose value can be changed with this function,\n"
-"  and this variable will be stored on the cdr.\n"
+"Here is a list of all the available cdr field names:\n"
+"     clid          lastdata       disposition\n"
+"     src           start          amaflags\n"
+"     dst           answer         accountcode\n"
+"     dcontext      end            uniqueid\n"
+"     dstchannel    duration       userfield\n"
+"     lastapp       billsec        channel\n"
+"All of the above variables are read-only, except for accountcode,\n"
+"userfield, and amaflags. You may, however,  supply\n"
+"a name not on the above list, and create your own\n"
+"variable, whose value can be changed with this function,\n"
+"and this variable will be stored on the cdr.\n"
 "   raw values for disposition:\n"
-"       1 = NO ANSWER\n"
-"	2 = BUSY\n"
-"	3 = FAILED\n"
-"	4 = ANSWERED\n"
+"     0 = NULL\n"
+"     1 = FAILED\n"
+"     2 = BUSY\n"
+"     4 = NO ANSWER\n"
+"     8 = ANSWERED\n"
 "    raw values for amaflags:\n"
-"       1 = OMIT\n"
-"       2 = BILLING\n"
-"       3 = DOCUMENTATION\n",
+"     1 = OMIT\n"
+"     2 = BILLING\n"
+"     3 = DOCUMENTATION\n"
+"If a third argument is supplied, it must be a handle that is returned\n"
+"by CDRstart(). In this case, any field can be set in the CDR associated\n"
+"with 'handle', except the start, answer and end times, which are set via the\n"
+"CDRstart(), CDRanswer() and CDRclose() functions, respectively. \n"
 };
 
+static int function_cdr_create(struct ast_channel *chan, const char *cmd,
+								   char *parse, char *buf, size_t len)
+{
+	struct ast_cdr *cdr = 0;
+	char *handle;
+
+	/* no args, no options so far */
+	
+	cdr = calloc(sizeof(struct ast_cdr),1);
+
+	if (!cdr) {
+		ast_log(LOG_ERROR,"CDRcreate could not allocate CDR memory!\n");
+	} else {
+		ast_cdr_init(cdr, chan);
+		
+		ast_cdr_start(cdr);
+	}
+	
+	asprintf(&handle, "%lu", (unsigned long)cdr);
+	
+	ast_copy_string(buf, handle, len);
+	free(handle);
+	
+	return 0;
+}
+
+static struct ast_custom_function cdr_create_function = {
+	.name = "CDRstart",
+	.synopsis = "Create and Start a non-attached CDR",
+	.syntax = "CDRstart()",
+	.desc =
+	"This function will create a CDR. This CDR will be initialized from the current channel,\n"
+	"and its start time will be set to the current time.\n" 
+	"It will return a 'handle' (a string of numbers) that can be used by the CDRanswer(),\n"
+	"the CDRclose() funcs to prepare and post a CDR. The CDR() function, given this handle,\n"
+	"can be used to modify any of the variables associated with this CDR.\n",
+	.read = function_cdr_create
+};
+
+static int function_cdr_answer(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(handle);
+	);
+
+	buf[0] = '\0';
+
+	if (ast_strlen_zero(parse)) {
+		ast_log(LOG_WARNING, "CDRanswer requires an argument, CDRanswer(<handle>)\n");
+		return -1;
+	}
+
+	AST_STANDARD_APP_ARGS(args, parse);
+
+	if (args.argc < 1) {
+		ast_log(LOG_WARNING, "CDRanswer requires an argument, CDRanswer(<handle>)\n");
+		return -1;
+	}
+
+	cdr = (struct ast_cdr*)strtoul(args.handle, NULL, 10);
+	ast_cdr_answer(cdr);
+	
+	ast_copy_string(buf, args.handle, len);
+	
+	return 0;
+}
+
+static struct ast_custom_function cdr_answer_function = {
+	.name = "CDRanswer",
+	.synopsis = "Sets the Answer time in the CDR associated with the supplied handle to the current time",
+	.syntax = "CDRanswer(handle)",
+	.desc =
+	"This function will Set the start time to the current time in the CDR associated with the argument 'handle'.\n"
+	" This func will return the handle.\n",
+	.read = function_cdr_answer
+};
+
+
+static int function_cdr_close(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(handle);
+	);
+
+	buf[0] = '\0';
+
+	if (ast_strlen_zero(parse)) {
+		ast_log(LOG_WARNING, "CDRclose requires an argument, CDRclose(<handle>)\n");
+		return -1;
+	}
+
+	AST_STANDARD_APP_ARGS(args, parse);
+
+	if (args.argc < 1) {
+		ast_log(LOG_WARNING, "CDRclose requires an argument, CDRclose(<handle>)\n");
+		return -1;
+	}
+
+	cdr = (struct ast_cdr*)strtoul(args.handle, NULL, 10);
+
+	ast_cdr_end(cdr);
+	ast_cdr_detach(cdr);
+	
+	ast_copy_string(buf, args.handle, len);
+	
+	return 0;
+}
+
+static struct ast_custom_function cdr_close_function = {
+	.name = "CDRclose",
+	.synopsis = "Sets the Answer time in the CDR associated with the supplied handle to the current time",
+	.syntax = "CDRclose(handle)",
+	.desc =
+	"This function will Set the start time to the current time in the CDR associated with the argument 'handle'.\n"
+	" This func will return the handle.\n",
+	.read = function_cdr_close
+};
+
+
 static int unload_module(void)
 {
-	return ast_custom_function_unregister(&cdr_function);
+	int res = 0;
+	
+	res = ast_custom_function_unregister(&cdr_function);
+	res |= ast_custom_function_unregister(&cdr_create_function);
+	res |= ast_custom_function_unregister(&cdr_answer_function);
+	res |= ast_custom_function_unregister(&cdr_close_function);
+	return res;
 }
 
 static int load_module(void)
 {
-	return ast_custom_function_register(&cdr_function);
-}
-
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call Detail Record (CDR) dialplan function");
+	int res = 0;
+	
+	res = ast_custom_function_register(&cdr_function);
+	res |= ast_custom_function_register(&cdr_create_function);
+	res |= ast_custom_function_register(&cdr_answer_function);
+	res |= ast_custom_function_register(&cdr_close_function);
+	return res;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call Detail Record (CDR) dialplan functions");



More information about the asterisk-commits mailing list