[asterisk-commits] murf: branch murf/cel2cdr r179217 - in /team/murf/cel2cdr: cel/ utils/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Feb 28 11:30:03 CST 2009


Author: murf
Date: Sat Feb 28 11:30:00 2009
New Revision: 179217

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=179217
Log:
check in initial pot-shots at the most important stuff... the stuff that will make testing this stuff easy.

Added:
    team/murf/cel2cdr/cel/
    team/murf/cel2cdr/cel/cel_cel2cdr.c   (with props)
    team/murf/cel2cdr/utils/csv2ev.c   (with props)
Modified:
    team/murf/cel2cdr/utils/Makefile

Added: team/murf/cel2cdr/cel/cel_cel2cdr.c
URL: http://svn.digium.com/svn-view/asterisk/team/murf/cel2cdr/cel/cel_cel2cdr.c?view=auto&rev=179217
==============================================================================
--- team/murf/cel2cdr/cel/cel_cel2cdr.c (added)
+++ team/murf/cel2cdr/cel/cel_cel2cdr.c Sat Feb 28 11:30:00 2009
@@ -1,0 +1,144 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2009, Digium, Inc.
+ *
+ * Steve Murphy <murf at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/* for simple CDRs:
+ */
+
+#include "asterisk/dlinkedlists.h"
+#include "asterisk/hashtab.h"
+
+struct event_list_member
+{
+	struct ast_event *ev;
+	AST_DLLIST_ENTRY(event_list_member) list;
+};
+
+struct event_list 
+{
+	char *linkedid; /* will be the channel name for simple CDR's; the linkedid for leg-based */
+
+	/* I'm trying to think of any other stuff I might need here... */
+
+	/* you know, maybe a DLL isn't so good here...
+	   the events may not arrive in order, due to the
+	   multiple thread nature of things. Mayhaps a priority
+	   queue (rbtrees, or Russell's heap stuff...? We'll figure
+	   it out soon. I think the requirements are these:
+	   a. insert an element into the list in order by event
+          time should be pretty quick. Mostly, new events should
+          be appended to the end.
+       b. I should be able to 'monkey' around the list pretty
+	      easily. Next(), Previous(), that sort of thing.
+       c. I think I'll be needing to remove chunks of the list
+          as they are 'used up' (a CDR posted). This should
+          be fast & painless 
+	*/
+	AST_DLLIST_ENTRY(event_list_member) list;
+};
+
+/* this hashtab is the central theme to the CDR approach.
+   Each event is filed into a list by their channel name (simple),
+   or by the linkedid (leg-based).
+*/
+static struct ast_hashtab *master_table = NULL;
+
+/* the funcs for hashing */
+
+static int table_compare_func(const void *a, const void *b)
+{
+	struct event_list *ev_a = a;
+	struct event list *ev_b = b;
+	return strcmp(ev_b->linkedid, ev_b->linkedid);
+}
+
+static unsigned int table_hash_func(const void *obj)
+{
+	struct event_list *obj_a = obj;
+	ast_hashtab_hash_string(obj_a->linkedid);
+}
+
+/* destruction is really boring stuff....
+   until it doesn't work, or doesn't work right! */
+
+void destroy_event_list_member(struct event_list_member *m)
+{
+	ast_event_destroy(m->ev);
+	m->ev = NULL;
+	free(m);
+}
+
+void destroy_event_list(struct event_list *l)
+{
+	struct event_list_member *m;
+	
+	AST_DLLIST_TRAVERSE_SAFE_BEGIN(&l->list, m, list) {
+		AST_DLLIST_REMOVE_CURRENT(list);
+		destroy_event_list_member(m);
+	}
+	AST_DLLIST_TRAVERSE_SAFE_END;
+	free(l->linkedid);
+	l->linkedid = NULL;
+	free(l);
+}
+
+
+/* mode == 0;  SIMPLE
+   mode == 1;  LEG_BASED
+*/
+
+enum cdr_mode_type { CEL2CDR_MODE_SIMPLE = 0, CEL2CDR_MODE_LEGBASED = 1 } ;
+
+enum cdr_mode_type cdr_mode = CEL2CDR_MODE_SIMPLE;
+static int cel2cdr_enabled = 0;
+
+static mod_load_func()
+{
+	/* read the config file, set all the control variables. */
+
+	/* set up the master table */
+	if (cel2cdr_enabled) {
+		if (!master_table) {
+			master_table = ast_hashtab_create(1001, table_compare_func, table_resize_func,
+											  table_newsize_func, table_hash_func, 1 /* do locking */);
+		} else {
+			/* this shouldn't happen? or should I just remove all the
+			   stuff from the table and leave it initialized? */
+		}
+	}
+}
+
+static mod_unload_func()
+{
+	if (master_table) {
+		ast_hashtab_destroy(master_table, destroy_event_list);
+		master_table = NULL;
+	}
+}
+
+
+void cel2cdr_handle_event(const struct ast_event *event, void *userdata)
+{
+	if (cel2cdr_enabled) {
+		if (cdr_mode == CEL2CDR_MODE_SIMPLE) {
+			/* save up start, answer, end event times and on END
+			   events, generate a CDR and post it */
+		} else { /* then LEGBASED by elimination! */
+
+		}
+	}
+}

Propchange: team/murf/cel2cdr/cel/cel_cel2cdr.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/murf/cel2cdr/cel/cel_cel2cdr.c
------------------------------------------------------------------------------
    svn:keywords = Author Id Date Revision

Propchange: team/murf/cel2cdr/cel/cel_cel2cdr.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/murf/cel2cdr/utils/Makefile
URL: http://svn.digium.com/svn-view/asterisk/team/murf/cel2cdr/utils/Makefile?view=diff&rev=179217&r1=179216&r2=179217
==============================================================================
--- team/murf/cel2cdr/utils/Makefile (original)
+++ team/murf/cel2cdr/utils/Makefile Sat Feb 28 11:30:00 2009
@@ -16,7 +16,7 @@
 
 .PHONY: clean all uninstall
 
-ALL_UTILS:=astman smsq stereorize streamplayer muted check_expr hashtest2 hashtest astcanary refcounter aelparse conf2ael
+ALL_UTILS:=astman smsq stereorize streamplayer muted check_expr hashtest2 hashtest astcanary refcounter aelparse conf2ael csv2cdr
 UTILS:=$(ALL_UTILS)
 
 LIBS += $(BKTR_LIB)	# astobj2 with devmode uses backtrace
@@ -132,10 +132,15 @@
 	$(ECHO_PREFIX) echo "   [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
 	$(CMD_PREFIX) cp "$<" "$@"
 
+csv2ev.o : csv2ev.c
+
 ael_main.o: ASTCFLAGS+=-DSTANDALONE
 
 aelparse.o: ASTCFLAGS+=-I$(ASTTOPDIR)/res -DSTANDALONE -Wno-unused
 aelparse: aelparse.o aelbison.o pbx_ael.o hashtab.o ael_main.o ast_expr2f.o ast_expr2.o strcompat.o pval.o extconf.o
+
+csv2cdr : csv2ev.o
+
 
 astobj2.c: $(ASTTOPDIR)/main/astobj2.c
 	$(ECHO_PREFIX) echo "   [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"

Added: team/murf/cel2cdr/utils/csv2ev.c
URL: http://svn.digium.com/svn-view/asterisk/team/murf/cel2cdr/utils/csv2ev.c?view=auto&rev=179217
==============================================================================
--- team/murf/cel2cdr/utils/csv2ev.c (added)
+++ team/murf/cel2cdr/utils/csv2ev.c Sat Feb 28 11:30:00 2009
@@ -1,0 +1,348 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2009, Digium, Inc.
+ *
+ * Steve Murphy <murf at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Routines ...routines to read in a csv formatted cel event file, and generate
+ *        event calls for the cel2cdr engine(s).
+ *
+ * \author Steve Murphy <murf at digium.com>
+ */
+
+#include "asterisk/event.h" /* which will include the event_defs.h also */
+#include "asterisk/linkedlists.h"
+#include "asterisk/extconf.h"
+#include "asterisk/cel.h"
+
+/* a simple linked list will represent what the user put in his cel_custom
+   config file... basically, we need the order of each field type.
+   we can then rocket the data off to the event calls */
+*/
+
+struct csv_list_mem
+{
+	enum ast_event_ie_type type;
+	AST_LIST_ENTRY(csv_list_mem) list;
+};
+
+struct csv_list
+{
+	AST_LIST_HEAD_NOLOCK(list, csv_list_mem);
+};
+
+enum ast_event_ie_type csv2ev_str2eventietype(char *str)
+{
+	/* hmmm, could we do a perfect hash of some sort? */
+	/* later maybe */
+	if (!strcmp(str,"${eventtype}")) {
+		return AST_EVENT_IE_CEL_EVENT_TYPE;
+	} else if (!strcmp(str,"${eventtime}")) {
+		return AST_EVENT_IE_CEL_EVENT_TIME;
+	} else if (!strcmp(str,"${CALLERID(name)}")) {
+		return AST_EVENT_IE_CEL_CIDNAME;
+	} else if (!strcmp(str,"${CALLERID(num)}")) {
+		return AST_EVENT_IE_CEL_CIDNUM;
+	} else if (!strcmp(str,"${CALLERID(ANI)}")) {
+		return AST_EVENT_IE_CEL_CIDANI;
+	} else if (!strcmp(str,"${CALLERID(RDNIS)}")) {
+		return AST_EVENT_IE_CEL_CIDRDNIS;
+	} else if (!strcmp(str,"${CALLERID(DNID)}")) {
+		return AST_EVENT_IE_CEL_CIDDNID;
+	} else if (!strcmp(str,"${CHANNEL(exten)}")) {
+		return AST_EVENT_IE_CEL_EXTEN;
+	} else if (!strcmp(str,"${CHANNEL(context)}")) {
+		return AST_EVENT_IE_CEL_CONTEXT;
+	} else if (!strcmp(str,"${CHANNEL(channame)}")) {
+		return AST_EVENT_IE_CEL_CHANNAME;
+	} else if (!strcmp(str,"${CHANNEL(appname)}")) {
+		return AST_EVENT_IE_CEL_APPNAME;
+	} else if (!strcmp(str,"${CHANNEL(appdata)}")) {
+		return AST_EVENT_IE_CEL_APPDATA;
+	} else if (!strcmp(str,"${CHANNEL(amaflags)}")) {
+		return AST_EVENT_IE_CEL_AMAFLAGS;
+	} else if (!strcmp(str,"${CHANNEL(accountcode)}")) {
+		return AST_EVENT_IE_CEL_ACCTCODE;
+	} else if (!strcmp(str,"${CHANNEL(uniqueid)}")) {
+		return AST_EVENT_IE_CEL_UNIQUEID;
+	} else if (!strcmp(str,"${CHANNEL(userfield)}")) {
+		return AST_EVENT_IE_CEL_USERFIELD;
+	} else if (!strcmp(str,"${CHANNEL(peer)}")) {
+		return AST_EVENT_IE_CEL_PEER;
+	} else if (!strcmp(str,"${CHANNEL(linkedid)}")) {
+		return AST_EVENT_IE_CEL_LINKEDID;
+	} else if (!strcmp(str,"${CHANNEL(peeracct)}")) {
+		return AST_EVENT_IE_CEL_PEERACCT;
+	} else {
+		printf("Hey!!! I do not understand what the cel_custom.conf field entry '%s' means!\n", str);
+		return AST_EVENT_IE_CEL_EXTRA;
+	}
+}
+
+
+struct csv_list *parse_mappings(char *val)
+{
+	struct csv_list *x = calloc(sizeof(struct csv_list),1);
+	char *beg1, *end1;
+	
+	if (!x) {
+		printf("Couldn't allocate a csv_list struct!\n");
+		return NULL;
+	}
+	
+	if (*val == '"')
+		val++;
+	if (val[strlen(val)-1] == '"') {
+		strcat(val,",\""); /* now every field is ended with the same char sequence! */
+	}
+	
+	while (beg1 = strstr(val,"\",\"")) {
+		*beg1 = 0;
+		/* val now points to the single entry, stripped of quotes */
+		struct csv_list_mem *m = calloc(sizeof(struct csv_list_mem),1);
+		if (!m) {
+			printf("Couldn't allocate a csv_list_mem struct!\n");
+			return NULL;
+		}
+		AST_LIST_INSERT_TAIL(x, m, list);
+		m->type = csv2ev_str2eventietype(val);
+		val = beg1+3;
+	}
+	
+	return x;
+}
+
+char *get_mappings(char *fname, char **fname)
+{
+	/* open the cel_custom file and get the first mappings value */
+	localized_use_conf_dir();
+	struct ast_config *f = localized_config_load(fname);
+	if (f) {
+		struct ast_category *m = localized_category_get(f, "mappings");
+		if (m) {
+			/* get the first variable */
+			if (m->root) {
+				printf("Found '%s => %s' in mappings!\n", m->root->name, m->root->name);
+				*fname = m->root->name;
+				return m->root->val;
+			} else {
+				printf("Sorry, but the mappings category was empty!\n");
+				return NULL;
+			}
+		} else {
+			printf("Sorry, the cel_custom.conf file had no mappings category!\n");
+			return NULL;
+		}
+	} else {
+		printf("Sorry, no cel_custom.conf file was found!\n");
+		return NULL;
+	}
+}
+
+void csv2events(void)
+{
+	
+	/* load the config file, then the csv file, and generate the events */
+	struct csv_list *csvlist, *csvptr;
+	char *fname;
+	char *mappings = get_mappings("cel_custom.conf", &fname);
+	if (mappings) {
+		csvlist = parse_mappings(char *val);
+		if (csvlist) {
+			/* OK, we know the order of each field. Watch out for usecs.
+			   Now, let's open the log file and begin event generation */
+			FILE *f;
+			char filename[512];
+			char buf[2048], *r;
+			
+			snprintf(filename, 512, "/var/log/asterisk/cel-custom/%s", fname);
+			f = fopen(filename, "r");
+			if (f) {
+				while (r=fgets(buf, sizeof(buf), f)) {
+					char *beg1, *val;
+					char *e_udef, *e_cid_name, *e_cid_num, *e_cid_ani, *e_cid_rdnis,
+						*e_cid_dnid, *e_exten, *e_context, *e_name, *e_appl, *e_appdata, *e_acctcode,
+						*e_peeracct, *e_uniqueid, *e_linkedid, *e_userfield, *e_extra, *e_peername;
+					unsigned int i_tvsec, i_tvusec, i_ama;
+					int i_type;
+					char *decptr;
+					
+					if (buf[strlen(buf)-1] != '\n') {
+						printf("Buffer size of %d was not large enough; tossing out input\n");
+						fgets(buf, sizeof(buf), f); /* hopefully, that was all there's left! */
+						continue;
+					} else {
+						buf[strlen(buf)-1] = 0;
+					}
+					/* we have a complete line from the cel-custom file */
+					if (strlen(buf)+3 < sizeof(buf)) {
+						printf("Buffer size exceeded for line: skipping.\n");
+						continue;
+					}
+					strcat(buf,",\""); /* now every field ends with the same pattern */
+					if (buf[0] == '"') {
+						val = buf + 1;
+					} else {
+						val = buf;
+					}
+					/* the temptation is strong to not use the event code to
+					   generate the event structs, so we don't have dependencies
+					   on taskprocessors and who knows what else in the asterisk
+					   core! */
+					csvptr = AST_LIST_FIRST(csvlist);
+					/* gather up the fields, and prepare for a the event call */
+					while (beg1 = strstr(val,"\",\"")) {
+						*beg1 = 0;
+						/* val now points to the single entry, stripped of quotes */
+						switch(csvptr->type)
+						{
+						case AST_EVENT_IE_CEL_EVENT_TYPE:
+							i_type = (int)ast_cel_str2eventtype(val);
+							if (i_type == -1) {
+								i_type = (int)CEL_USER_DEFINED;
+								e_udef = val;
+							} else {
+								e_udef = "";
+							}
+							
+							break;
+						case AST_EVENT_IE_CEL_EVENT_TIME:
+							i_tvsec = strtol(val, NULL, 10);
+							decptr = strchr(val,'.');
+							if (decptr) {
+								i_tvusec = strlol(decptr+1, NULL, 10);
+							} else {
+								i_tvusec = 0;
+							}
+							break;
+						case AST_EVENT_IE_CEL_CIDNAME:
+							e_cid_name = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_CIDNUM:
+							e_cid_num = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_CIDANI:
+							e_cid_ani = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_CIDRDNIS:
+							e_cid_rdnis = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_CIDDNID:
+							e_cid_dnid = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_EXTEN:
+							e_exten = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_CONTEXT:
+							e_context = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_CHANNAME:
+							e_name = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_APPNAME:
+							e_appl = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_APPDATA:
+							e_appdata = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_AMAFLAGS:
+							i_ama = atoi(val);
+							break;
+							
+						case AST_EVENT_IE_CEL_ACCTCODE:
+							e_acctcode = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_UNIQUEID:
+							e_uniqueid = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_USERFIELD:
+							e_userfield = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_PEER:
+							e_peername = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_LINKEDID:
+							e_linkedid = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_PEERACCT:
+							e_peeracct = val;
+							break;
+							
+						case AST_EVENT_IE_CEL_EXTRA:
+							e_extra = val;
+							break;
+						}
+						csvptr = AST_LIST_NEXT(csvptr,list);
+						val = beg1+3;
+					}
+					/* this is a lot of trouble for a standalone to go to to pass this
+					   info to the cdr generator, but... we want it to be the same interface
+					   at that end, whether within asterisk, or in a standalone. No code
+					   duplication that way. */
+					ev = ast_event_new(AST_EVENT_CEL,
+									   AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, (unsigned int)i_type,
+									   AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, i_tvsec,
+									   AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, i_tvusec,
+									   AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, e_udef,
+									   AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, e_cid_name,
+									   AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, e_cid_num,
+									   AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR, e_cid_ani,
+									   AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR, e_cid_rdnis,
+									   AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR, e_cid_dnid,
+									   AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, e_exten,
+									   AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, e_context,
+									   AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, e_name,
+									   AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, e_appl,
+									   AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, e_appdata,
+									   AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, i_ama,
+									   AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, e_acctcode,
+									   AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, e_peeracct,
+									   AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, e_uniqueid,
+									   AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, e_linkedid,
+									   AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, e_userfield,
+									   AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, e_extra,
+									   AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, e_peername,
+									   AST_EVENT_IE_END);
+					if (!ev) {
+						ast_log(LOG_NOTICE,"NULL event returned\n");
+						return;
+					}
+					/* now, directly call the handler in the cel2cdr.c file */
+					cel2cdr_handle_event(ev, NULL); /* userdata, anyone?? */
+				}
+			} else {
+				printf("Couldn't open %s for read!\n", filename);
+				exit(11);
+			}
+		}
+	}
+}

Propchange: team/murf/cel2cdr/utils/csv2ev.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/murf/cel2cdr/utils/csv2ev.c
------------------------------------------------------------------------------
    svn:keywords = Author Id Date Revision

Propchange: team/murf/cel2cdr/utils/csv2ev.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the asterisk-commits mailing list