Permalink
Browse files

Modified to work with asterisk-1.8

  • Loading branch information...
1 parent 20a4ca0 commit 8f64bfe8177a42f2b4f54baf5f1d0a6a58dc3376 @pruiz committed Feb 11, 2012
Showing with 362 additions and 119 deletions.
  1. +2 −2 Makefile
  2. +222 −0 README
  3. +138 −117 cdr_yada.c
View
4 Makefile
@@ -14,8 +14,8 @@ YADA_PATH=/usr/local
UFP_LDADD=hash/hash.o hash/bufkey.o
CC=gcc
-LD=gcc -shared -Xlinker -x
-CFLAGS=-Wall -g
+LD=gcc -shared -Xlinker -x -g3 -ggdb3
+CFLAGS=-Wall -g3 -ggdb3 -O0
CPPFLAGS=$(DEFINES) $(INCLUDES)
LDFLAGS=-L$(YADA_PATH)/lib
View
222 README
@@ -0,0 +1,222 @@
+
+cdr_yada
+Copyright 2004 - 2006 Matt Griswold, dev/IT
+Released under the GNU General Public License, see COPYING
+Latest version at http://oss.devit.com/voip/asterisk/cdr_yada/
+
+################################################################################
+# description
+
+This is a call detail recording (CDR) module for asterisk and is used to
+store call details to any database yada supports (currently MySQL, Oracle,
+PostgreSQL, SQLite3).
+
+If the database is not available, it can queue records to both memory and disc
+for later playback without worry of losing records.
+
+asterisk: http://asterisk.org/
+yada: http://oss.devit.com/yada/
+
+################################################################################
+# custom userfield parsing
+
+This feature, sponsored by voipGATE.com, allows custom cdr fields to be input
+via the SetCDRUserField function. For example, you could define 3 columns
+(col1, col2, col3) and set any or all of them by calling
+SetCDRUserField(col1=yes, col3=${CALLERID}) and they would be parsed and put
+into the database in their respective columns.
+
+To define the columns, you must set a name=<COLUMN NAME> in a config section refering to the column it's in. There are 16 possible columns, ufc0 - ufc15.
+
+[ufc0]
+ name=col1
+
+See example at bottom of this file for more information.
+
+################################################################################
+# installation
+
+Untar this source into your asterisk source directory. cd into the cdr_yada
+directory, review any variables in the Makefile, and type 'make'.
+
+Copy cdr_yada.so to your asterisk module directory (default
+/usr/lib/asterisk/modules). Copy cdr_yada.conf.sample as cdr_yada.conf into
+your asterisk config directory (default /etc/asterisk) and edit it.
+
+################################################################################
+# asterisk cli commands
+
+cdr yada connect :
+ connect to database
+
+cdr yada disconnect :
+ sync any queued logs and disconnect from database
+
+cdr yada status :
+ display current status
+
+################################################################################
+# config example
+
+;
+; cdr_yada.conf
+;
+
+[global]
+
+ ; yada db string to connect to
+ dbstr=mysql:localhost::cdr
+ ; username for db (if required)
+ user=cdr
+ ; password for db (if required)
+ pass=cdrpass
+
+ ; maximum number of records to hold in memory
+ ; once this is reached, records are either written to disc or dropped
+ queue_size=500
+ queue_file=/var/asterisk/cdr_yada.queue
+
+ ; this option sets whether or not to playback records from the queue_file
+ ; if set to no, it will not play them back and you will need to do it manually
+ ; this is primarily used if doing so would cause load issues
+ ;queue_playback=yes
+
+ ; table name
+ table=cdr_record
+
+ ; query to use to insert records
+ ; note: table directive is ignored if query directive is used
+ ;query=
+
+
+################################################################################
+# example schema (in MySQL)
+
+create table cdr_yada (
+ id int not null,
+ calldate datetime not null default '0000-00-00 00:00:00',
+ accountcode varchar(20) not null default '',
+ src varchar(80) not null default '',
+ dst varchar(80) not null default '',
+ dcontext varchar(80) not null default '',
+ clid varchar(80) not null default '',
+ channel varchar(80) not null default '',
+ dstchannel varchar(80) not null default '',
+ lastapp varchar(80) not null default '',
+ lastdata varchar(80) not null default '',
+ duration int(11) not null default '0',
+ billsec int(11) not null default '0',
+ disposition varchar(45) not null default '',
+ amaflags int(11) not null default '0',
+ uniqueid varchar(32) not null default '',
+ userfield varchar(255) not null default ''
+);
+
+with config directive
+
+ table=cdr_yada
+
+################################################################################
+# example custom schema
+
+create table cdr_yada_cust (
+ id int not null,
+ calldate datetime not null default '0000-00-00 00:00:00',
+ accountcode varchar(20) not null default '',
+ src varchar(80) not null default '',
+ dst varchar(80) not null default '',
+ dcontext varchar(80) not null default '',
+ clid varchar(80) not null default '',
+ channel varchar(80) not null default '',
+ dstchannel varchar(80) not null default '',
+ lastapp varchar(80) not null default '',
+ lastdata varchar(80) not null default '',
+ duration int(11) not null default '0',
+ billsec int(11) not null default '0',
+ disposition varchar(45) not null default '',
+ amaflags int(11) not null default '0'
+);
+
+with config directive
+
+ query=insert into cdr_yada_cust (calldate, clid, src, dst, dcontext, channel, dstchannel, lastapp, lastdata, duration, billsec, disposition, amaflags) values ('?s', ?v, ?v, ?v, ?v, ?v, ?v, ?v, ?v, ?d, ?d, ?v, ?d)
+
+################################################################################
+# example oracle schema and query to make the date work properly
+# (thanks Han van Hulst)
+
+ Name Null? Type
+ ------------------- -------- ----------------
+ ID NUMBER(38)
+ CALLDATE DATE
+ ACCOUNTCODE VARCHAR2(20)
+ SRC VARCHAR2(80)
+ DST VARCHAR2(80)
+ DCONTEXT VARCHAR2(80)
+ CLID VARCHAR2(80)
+ CHANNEL VARCHAR2(80)
+ DSTCHANNEL VARCHAR2(80)
+ LASTAPP VARCHAR2(80)
+ LASTDATA VARCHAR2(80)
+ DURATION NUMBER(38)
+ BILLSEC NUMBER(38)
+ DISPOSITION VARCHAR2(45)
+ AMAFLAGS NUMBER(38)
+ UNIQUEID VARCHAR2(32)
+ USERFIELD VARCHAR2(255)
+
+ query=insert into cdr_yada (id,calldate, clid, src, dst, dcontext, channel, dstchannel, lastapp, lastdata, duration, billsec, disposition, amaflags, accountcode, uniqueid, userfield) values (cdrseq.nextval, to_date('?s','yyyy-mm-dd hh24:mi:ss'), ?v, ?v, ?v, ?v, ?v, ?v, ?v, ?v, ?d, ?d, ?v, ?d, ?v, ?v, ?v)
+
+################################################################################
+# example custom userfield schema (in MySQL)
+
+create table cdr_yada_ufp (
+ id int not null,
+ calldate datetime not null default '0000-00-00 00:00:00',
+ accountcode varchar(20) not null default '',
+ src varchar(80) not null default '',
+ dst varchar(80) not null default '',
+ dcontext varchar(80) not null default '',
+ clid varchar(80) not null default '',
+ channel varchar(80) not null default '',
+ dstchannel varchar(80) not null default '',
+ lastapp varchar(80) not null default '',
+ lastdata varchar(80) not null default '',
+ duration int(11) not null default '0',
+ billsec int(11) not null default '0',
+ disposition varchar(45) not null default '',
+ amaflags int(11) not null default '0',
+ uniqueid varchar(32) not null default '',
+ msg varchar(255),
+ area varchar(255),
+ cid varchar(255),
+);
+
+
+ table=cdr_yada_ufp
+
+[userfield_parse]
+ enabled=yes
+
+[ufc0]
+ name=msg
+
+[ufc1]
+ name=area
+
+[ufc2]
+ name=cid
+
+set in the dialplan with:
+
+SetCDRUserField(msg=test message, area=555, cid=${CALLERID})
+
+################################################################################
+# contact
+
+Questions, comments, bugs, etc.
+
+Matt Griswold <matt@devit.com> 0x6B2E514F
+6CF4 A97B 55A5 BBD6 FF06 6F0B F99D 7C86 6B2E 514F
+http://oss.devit.com/matt/
+
View
255 cdr_yada.c
@@ -141,21 +141,6 @@ int ufv_sz;
char **ufv = 0, *ufvp;
hash_t *ufp_h = 0;
-/******************************************************************************/
-/* cli command help */
-
-static char cdr_yada_connect_help[] =
- "Usage: cdr yada connect\n"
- " Make cdr_yada connect to the database\n";
-
-static char cdr_yada_disconnect_help[] =
- "Usage: cdr yada disconnect\n"
- " Disconnect cdr_yada from database\n";
-
-static char cdr_yada_status_help[] =
- "Usage: cdr yada status\n"
- " Show current status for cdr_yada\n";
-
/******************************************************************************
* F U N C T I O N S **********************************************************
******************************************************************************/
@@ -290,22 +275,26 @@ static inline void cdr_yada_process_queue()
/** check for database connection, connecting if able
*/
-static inline int db_ping()
+static int db_ping()
{
+ ast_verbose(VERBOSE_PREFIX_1 "PING..\n");
+
if(yada && connected)
return(1);
if(opt_nodb)
return(0);
if(!yada)
- {
+ {
+ ast_verbose(VERBOSE_PREFIX_1 "Connecting..\n");
+
/* init and connect to yada */
if(!(yada = yada_init(dbstr, 0)))
- {
+ {
ast_log(LOG_ERROR, "Failed to initialize yada: %s\n", strerror(errno));
return(0);
- }
+ }
/* prepare insert */
if(query == DEFAULT_QUERY)
@@ -314,13 +303,13 @@ static inline int db_ping()
stmt_ins = yada->yprepare(yada, query, 0);
if(!stmt_ins)
- {
+ {
ast_log(LOG_ERROR, "Failed to prepare insert: %s\n", yada->errmsg);
yada->destroy(yada);
yada = 0;
return(0);
- }
}
+ }
/* connect and check for queued logs */
if(!yada->connect(yada, user, pass))
@@ -370,84 +359,139 @@ static inline void db_destroy()
/** cli to connect to database
*/
-static int cdr_yada_connect(int fd, int argc, char *argv[])
+static char *cdr_yada_connect(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- opt_nodb = 0;
-
+ static const char* const choices[] = { "cdr", "yada", "connect", NULL };
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "cdr yada connect";
+ e->usage =
+ "Usage: cdr yada connect\n"
+ " Make cdr_yada connect to the database\n";
+ return NULL;
+
+ case CLI_GENERATE:
+ if (a->pos > e->args)
+ return NULL;
+ return ast_cli_complete(a->word, choices, a->n);
+
+ default:
+ // we are guaranteed to be called with argc >= e->args;
+ if (a->argc > e->args + 1) // we accept one extra argument
+ return CLI_SHOWUSAGE;
+
+ if(yada && connected)
+ {
+ ast_cli(a->fd, "cdr_yada: database allready connected\n");
+ return (CLI_SUCCESS);
+ }
- if(yada && connected)
- {
- ast_cli(fd, "cdr_yada: database allready connected\n");
- return(RESULT_SUCCESS);
- }
+ opt_nodb = 0;
- if(!db_ping())
- {
- ast_cli(fd, "cdr_yada: unable to connect to database: %s\n", yada->errmsg);
- return(RESULT_FAILURE);
- }
+ if(!db_ping())
+ {
+ char *errmsg = yada != NULL ? yada->errmsg : "unknown";
+ ast_cli(a->fd, "cdr_yada: unable to connect to database: %s\n", errmsg);
+ return (CLI_FAILURE);
+ }
- ast_cli(fd, "cdr_yada: database connected\n");
- return(RESULT_SUCCESS);
+ ast_cli(a->fd, "cdr_yada: database connected\n");
+ //ast_cli(a->fd, "done this well for %s\n", e->args[argc-1]);
+ return (CLI_SUCCESS);
+ }
}
/******************************************************************************/
/** cli to disconnect to database
*/
-static int cdr_yada_disconnect(int fd, int argc, char *argv[])
+static char *cdr_yada_disconnect(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- opt_nodb = 1;
+ static const char *const choices[] = { "cdr", "yada", "disconnect", NULL };
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "cdr yada disconnect";
+ e->usage =
+ "Usage: cdr yada disconnect\n"
+ " Disconnect cdr_yada from database\n";
+ return NULL;
- if(!yada || !connected)
- {
- ast_cli(fd, "cdr_yada: database is not connected\n");
- return(RESULT_SUCCESS);
- }
+ case CLI_GENERATE:
+ if (a->pos > e->args)
+ return NULL;
+ return ast_cli_complete(a->word, choices, a->n);
- db_disco();
+ default:
- ast_cli(fd, "cdr_yada: database disconnected\n");
- return(RESULT_SUCCESS);
+ if(!yada || !connected)
+ {
+ ast_cli(a->fd, "cdr_yada: database is not connected\n");
+ return (CLI_SUCCESS);
+ }
+
+ opt_nodb = 1;
+
+ db_disco();
+
+ ast_cli(a->fd, "cdr_yada: database disconnected\n");
+ return (CLI_SUCCESS);
+ }
}
/******************************************************************************/
/** cli to get status
*/
-static int cdr_yada_status(int fd, int argc, char *argv[])
+static char *cdr_yada_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
int ctime = time(0) - act_time;
-
-
- ast_cli(fd, "cdr_yada %s\n", rev);
-
- if(connected)
- {
- ast_cli(fd, "Connected to '%s'", dbstr);
- if(user)
- ast_cli(fd, " as '%s'", user);
- }
- else
- ast_cli(fd, "Not connected");
-
- if(ctime > 86400)
- ast_cli(fd, " for %dd%dh%dm%ds.\n", ctime / 86400, (ctime % 86400) / 3600,
- (ctime % 3600) / 60, ctime % 60);
- else if(ctime > 3600)
- ast_cli(fd, " for %dh%dm%ds.\n", ctime / 3600, (ctime % 3600) / 60,
- ctime % 60);
- else if(ctime > 60)
- ast_cli(fd, " for %dm%ds.\n", ctime / 60, ctime % 60);
- else
- ast_cli(fd, " for %ds.\n", ctime);
-
- ast_cli(fd, "%d of %d records queued, %d errors\n", queue_cnt, queue_size,
- error_cnt);
- ast_cli(fd, "queue_file is %s\n", queue_file ? queue_file : "not set");
- ast_cli(fd, "\n");
- return(RESULT_SUCCESS);
+ static const char *const choices[] = { "cdr", "yada", "status", NULL };
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "cdr yada status";
+ e->usage =
+ "Usage: cdr yada status\n"
+ " Show current status for cdr_yada\n";
+ return NULL;
+
+ case CLI_GENERATE:
+ if (a->pos > e->args)
+ return NULL;
+ return ast_cli_complete(a->word, choices, a->n);
+
+ default:
+
+ ast_cli(a->fd, "cdr_yada %s\n", rev);
+
+ if(connected)
+ {
+ ast_cli(a->fd, "Connected to '%s'", dbstr);
+ if(user)
+ ast_cli(a->fd, " as '%s'", user);
+ }
+ else
+ ast_cli(a->fd, "Not connected");
+
+ if(ctime > 86400)
+ ast_cli(a->fd, " for %dd%dh%dm%ds.\n", ctime / 86400, (ctime % 86400) / 3600,
+ (ctime % 3600) / 60, ctime % 60);
+ else if(ctime > 3600)
+ ast_cli(a->fd, " for %dh%dm%ds.\n", ctime / 3600, (ctime % 3600) / 60,
+ ctime % 60);
+ else if(ctime > 60)
+ ast_cli(a->fd, " for %dm%ds.\n", ctime / 60, ctime % 60);
+ else
+ ast_cli(a->fd, " for %ds.\n", ctime);
+
+ ast_cli(a->fd, "%d of %d records queued, %d errors\n", queue_cnt, queue_size,
+ error_cnt);
+ ast_cli(a->fd, "queue_file is %s\n", queue_file ? queue_file : "not set");
+ ast_cli(a->fd, "\n");
+ return (CLI_SUCCESS);
+ }
}
/******************************************************************************/
@@ -499,7 +543,7 @@ static inline int grow_ufv(size_t sz)
static char** parse_uf(char *userfield)
{
- int idx = -1, len;
+ size_t idx = -1, len;
char *ptr, *start;
char *ufvp;
@@ -537,7 +581,7 @@ static char** parse_uf(char *userfield)
case('='):
/* get index of variable */
- if((idx = (int)hash_get(ufp_h, start, ptr - start) - 1) == -1)
+ if((idx = (size_t)hash_get(ufp_h, start, ptr - start) - 1) == -1)
{
ast_log(LOG_WARNING, "Skipping unknown variable starting at %s\n",
start);
@@ -574,15 +618,15 @@ static char** parse_uf(char *userfield)
static int cdr_yada_ufp_log(struct ast_cdr *cdr)
{
- struct tm tm;
+ struct ast_tm tm;
static char timestr[128];
char *qstr;
ast_mutex_lock(&cdr_yada_lock);
- ast_localtime(&cdr->start.tv_sec, &tm, NULL);
- strftime(timestr, 128, DATE_FORMAT, &tm);
+ ast_localtime(&cdr->start, &tm, NULL);
+ ast_strftime(timestr, 128, DATE_FORMAT, &tm);
/* parse userfield into vars */
if(!parse_uf(cdr->userfield))
@@ -653,15 +697,15 @@ static int cdr_yada_ufp_log(struct ast_cdr *cdr)
static int cdr_yada_log(struct ast_cdr *cdr)
{
- struct tm tm;
+ struct ast_tm tm;
static char timestr[128];
char *qstr;
ast_mutex_lock(&cdr_yada_lock);
- ast_localtime(&cdr->start.tv_sec, &tm, NULL);
- strftime(timestr, 128, DATE_FORMAT, &tm);
+ ast_localtime(&cdr->start, &tm, NULL);
+ ast_strftime(timestr, 128, DATE_FORMAT, &tm);
/* try to write to db */
if(db_ping())
@@ -717,31 +761,10 @@ static int cdr_yada_log(struct ast_cdr *cdr)
/******************************************************************************/
/* cli definitions */
-static struct ast_cli_entry cdr_yada_cli_connect =
-{
- { "cdr", "yada", "connect", NULL },
- cdr_yada_connect,
- "Connect database from cdr_yada",
- cdr_yada_connect_help,
- NULL
-};
-
-static struct ast_cli_entry cdr_yada_cli_disconnect =
-{
- { "cdr", "yada", "disconnect", NULL },
- cdr_yada_disconnect,
- "Disconnect database from cdr_yada",
- cdr_yada_disconnect_help,
- NULL
-};
-
-static struct ast_cli_entry cdr_yada_cli_status =
-{
- { "cdr", "yada", "status", NULL },
- cdr_yada_status,
- "Show current status of cdr_yada",
- cdr_yada_status_help,
- NULL
+static struct ast_cli_entry cdr_yada_cmds[] = {
+ AST_CLI_DEFINE(cdr_yada_connect, "Connect database from cdr_yada"),
+ AST_CLI_DEFINE(cdr_yada_disconnect, "Disconnect database from cdr_yada"),
+ AST_CLI_DEFINE(cdr_yada_status, "Show current status of cdr_yada")
};
/******************************************************************************/
@@ -750,7 +773,8 @@ static struct ast_cli_entry cdr_yada_cli_status =
static inline int ufp_init(struct ast_config *cfg)
{
- int i, idx, csz, vsz;
+ size_t idx;
+ int i, csz, vsz;
char *new, ufc[6];
char *clist = 0, *vlist = 0, *clp, *vlp;
const char *colname;
@@ -870,9 +894,10 @@ static int cdr_yada_load(void)
struct ast_variable *var;
const char *tmp;
ast_cdrbe logger;
+ struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
- if(!(cfg = ast_config_load(config)))
+ if(!(cfg = ast_config_load(config, config_flags)))
{
ast_log(LOG_WARNING, "Aborting: failed to load config: %s\n", config);
return(AST_MODULE_LOAD_DECLINE);
@@ -982,9 +1007,7 @@ static int cdr_yada_load(void)
errjmp("Failed to register cdr_yada\n");
/* register cli */
- if(ast_cli_register(&cdr_yada_cli_connect) ||
- ast_cli_register(&cdr_yada_cli_disconnect) ||
- ast_cli_register(&cdr_yada_cli_status))
+ if (ast_cli_register_multiple(cdr_yada_cmds, ARRAY_LEN(cdr_yada_cmds)))
errjmp("Failed to register cli 'connect'\n");
ast_config_destroy(cfg);
@@ -1008,9 +1031,7 @@ int cdr_yada_unload(void)
/* destroy yada */
db_destroy();
- ast_cli_unregister(&cdr_yada_cli_connect);
- ast_cli_unregister(&cdr_yada_cli_disconnect);
- ast_cli_unregister(&cdr_yada_cli_status);
+ ast_cli_unregister_multiple(cdr_yada_cmds, ARRAY_LEN(cdr_yada_cmds));
ast_cdr_unregister(name);
return(RESULT_SUCCESS);

0 comments on commit 8f64bfe

Please sign in to comment.