Asterisk - The Open Source Telephony Project  GIT-master-a24979a
Macros | Functions | Variables
cdr_csv.c File Reference

Comma Separated Value CDR records. More...

#include "asterisk.h"
#include "asterisk/paths.h"
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/module.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
Include dependency graph for cdr_csv.c:

Go to the source code of this file.

Macros

#define CSV_LOG_DIR   "/cdr-csv"
 
#define CSV_MASTER   "/Master.csv"
 
#define DATE_FORMAT   "%Y-%m-%d %T"
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int append_date (char *buf, struct timeval when, size_t bufsize)
 
static int append_int (char *buf, int s, size_t bufsize)
 
static int append_string (char *buf, const char *s, size_t bufsize)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int build_csv_record (char *buf, size_t bufsize, struct ast_cdr *cdr)
 
static int csv_log (struct ast_cdr *cdr)
 
static int load_config (int reload)
 
static int load_module (void)
 
static int reload (void)
 
static int unload_module (void)
 
static int writefile (char *s, char *file_path)
 
static int writefile_account (char *s, char *acc)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Comma Separated Values CDR Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, .requires = "cdr", }
 
static int accountlogs = 1
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const char config [] = "cdr.conf"
 
static ast_mutex_t f_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static char file_csv_master [PATH_MAX]
 
static int loaded = 0
 
static int loguniqueid = 0
 
static int loguserfield = 0
 
static char * name = "csv"
 
static int newcdrcolumns = 0
 
static int usegmtime = 0
 

Detailed Description

Comma Separated Value CDR records.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file cdr_csv.c.

Macro Definition Documentation

◆ CSV_LOG_DIR

#define CSV_LOG_DIR   "/cdr-csv"

Definition at line 49 of file cdr_csv.c.

◆ CSV_MASTER

#define CSV_MASTER   "/Master.csv"

Definition at line 50 of file cdr_csv.c.

◆ DATE_FORMAT

#define DATE_FORMAT   "%Y-%m-%d %T"

Definition at line 52 of file cdr_csv.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 364 of file cdr_csv.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 364 of file cdr_csv.c.

◆ append_date()

static int append_date ( char *  buf,
struct timeval  when,
size_t  bufsize 
)
static

Definition at line 192 of file cdr_csv.c.

193 {
194  char tmp[80] = "";
195  struct ast_tm tm;
196 
197  if (strlen(buf) > bufsize - 3)
198  return -1;
199 
200  if (ast_tvzero(when)) {
201  strncat(buf, ",", bufsize - strlen(buf) - 1);
202  return 0;
203  }
204 
205  ast_localtime(&when, &tm, usegmtime ? "GMT" : NULL);
206  ast_strftime(tmp, sizeof(tmp), DATE_FORMAT, &tm);
207 
208  return append_string(buf, tmp, bufsize);
209 }
static int tmp()
Definition: bt_open.c:389
static int append_string(char *buf, const char *s, size_t bufsize)
Definition: cdr_csv.c:147
static int usegmtime
Definition: cdr_csv.c:54
#define DATE_FORMAT
Definition: cdr_csv.c:52
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
#define NULL
Definition: resample.c:96
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:115

References append_string(), ast_localtime(), ast_strftime(), ast_tvzero(), buf, DATE_FORMAT, NULL, tmp(), and usegmtime.

Referenced by build_csv_record().

◆ append_int()

static int append_int ( char *  buf,
int  s,
size_t  bufsize 
)
static

Definition at line 174 of file cdr_csv.c.

175 {
176  char tmp[32];
177  int pos = strlen(buf);
178 
179  snprintf(tmp, sizeof(tmp), "%d", s);
180 
181  if (pos + strlen(tmp) > bufsize - 3)
182  return -1;
183 
184  strncat(buf, tmp, bufsize - strlen(buf) - 1);
185  pos = strlen(buf);
186  buf[pos++] = ',';
187  buf[pos++] = '\0';
188 
189  return 0;
190 }

References buf, and tmp().

Referenced by build_csv_record().

◆ append_string()

static int append_string ( char *  buf,
const char *  s,
size_t  bufsize 
)
static

Definition at line 147 of file cdr_csv.c.

148 {
149  int pos = strlen(buf), spos = 0, error = -1;
150 
151  if (pos >= bufsize - 4)
152  return -1;
153 
154  buf[pos++] = '\"';
155 
156  while(pos < bufsize - 3) {
157  if (!s[spos]) {
158  error = 0;
159  break;
160  }
161  if (s[spos] == '\"')
162  buf[pos++] = '\"';
163  buf[pos++] = s[spos];
164  spos++;
165  }
166 
167  buf[pos++] = '\"';
168  buf[pos++] = ',';
169  buf[pos++] = '\0';
170 
171  return error;
172 }
int error(const char *format,...)
Definition: utils/frame.c:999

References buf, and error().

Referenced by append_date(), and build_csv_record().

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 364 of file cdr_csv.c.

◆ build_csv_record()

static int build_csv_record ( char *  buf,
size_t  bufsize,
struct ast_cdr cdr 
)
static

Definition at line 211 of file cdr_csv.c.

212 {
213 
214  buf[0] = '\0';
215  /* Account code */
216  append_string(buf, cdr->accountcode, bufsize);
217  /* Source */
218  append_string(buf, cdr->src, bufsize);
219  /* Destination */
220  append_string(buf, cdr->dst, bufsize);
221  /* Destination context */
222  append_string(buf, cdr->dcontext, bufsize);
223  /* Caller*ID */
224  append_string(buf, cdr->clid, bufsize);
225  /* Channel */
226  append_string(buf, cdr->channel, bufsize);
227  /* Destination Channel */
228  append_string(buf, cdr->dstchannel, bufsize);
229  /* Last Application */
230  append_string(buf, cdr->lastapp, bufsize);
231  /* Last Data */
232  append_string(buf, cdr->lastdata, bufsize);
233  /* Start Time */
234  append_date(buf, cdr->start, bufsize);
235  /* Answer Time */
236  append_date(buf, cdr->answer, bufsize);
237  /* End Time */
238  append_date(buf, cdr->end, bufsize);
239  /* Duration */
240  append_int(buf, cdr->duration, bufsize);
241  /* Billable seconds */
242  append_int(buf, cdr->billsec, bufsize);
243  /* Disposition */
245  /* AMA Flags */
247  /* Unique ID */
248  if (loguniqueid)
249  append_string(buf, cdr->uniqueid, bufsize);
250  /* append the user field */
251  if(loguserfield)
252  append_string(buf, cdr->userfield, bufsize);
253  if (newcdrcolumns) {
254  append_string(buf, cdr->peeraccount, bufsize);
255  append_string(buf, cdr->linkedid, bufsize);
256  append_int(buf, cdr->sequence, bufsize);
257  }
258  /* If we hit the end of our buffer, log an error */
259  if (strlen(buf) < bufsize - 5) {
260  /* Trim off trailing comma */
261  buf[strlen(buf) - 1] = '\0';
262  strncat(buf, "\n", bufsize - strlen(buf) - 1);
263  return 0;
264  }
265  return -1;
266 }
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:3452
static int append_date(char *buf, struct timeval when, size_t bufsize)
Definition: cdr_csv.c:192
static int loguserfield
Definition: cdr_csv.c:57
static int loguniqueid
Definition: cdr_csv.c:56
static int append_int(char *buf, int s, size_t bufsize)
Definition: cdr_csv.c:174
static int newcdrcolumns
Definition: cdr_csv.c:59
const char * ast_channel_amaflags2string(enum ama_flags flags)
Convert the enum representation of an AMA flag to a string representation.
Definition: channel.c:4408
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:289
long int disposition
Definition: cdr.h:305
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:293
char linkedid[AST_MAX_UNIQUEID]
Definition: cdr.h:317
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:319
long int billsec
Definition: cdr.h:303
struct timeval answer
Definition: cdr.h:297
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:287
char peeraccount[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:311
long int duration
Definition: cdr.h:301
long int amaflags
Definition: cdr.h:307
char src[AST_MAX_EXTENSION]
Definition: cdr.h:281
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:283
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:279
char uniqueid[AST_MAX_UNIQUEID]
Definition: cdr.h:315
int sequence
Definition: cdr.h:321
struct timeval start
Definition: cdr.h:295
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:309
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:291
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:285
struct timeval end
Definition: cdr.h:299

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, append_date(), append_int(), append_string(), ast_cdr_disp2str(), ast_channel_amaflags2string(), ast_cdr::billsec, buf, ast_cdr::channel, ast_cdr::clid, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::end, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::linkedid, loguniqueid, loguserfield, newcdrcolumns, ast_cdr::peeraccount, ast_cdr::sequence, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.

Referenced by csv_log().

◆ csv_log()

static int csv_log ( struct ast_cdr cdr)
static

Definition at line 297 of file cdr_csv.c.

298 {
299  /* Make sure we have a big enough buf */
300  char buf[1024];
301  if (build_csv_record(buf, sizeof(buf), cdr)) {
302  ast_log(LOG_WARNING, "Unable to create CSV record in %d bytes. CDR not recorded!\n", (int)sizeof(buf));
303  return 0;
304  }
305 
308  ast_log(LOG_WARNING, "Unable to write CSV record to master '%s' : %s\n", file_csv_master, strerror(errno));
309 
310  if (accountlogs && !ast_strlen_zero(cdr->accountcode)) {
311  if (writefile_account(buf, cdr->accountcode))
312  ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s' : %s\n", cdr->accountcode, strerror(errno));
313  }
315  return 0;
316 }
#define ast_log
Definition: astobj2.c:42
static int writefile_account(char *s, char *acc)
Definition: cdr_csv.c:286
static int writefile(char *s, char *file_path)
Definition: cdr_csv.c:268
static int accountlogs
Definition: cdr_csv.c:55
static ast_mutex_t f_lock
Definition: cdr_csv.c:96
static char file_csv_master[PATH_MAX]
Definition: cdr_csv.c:61
static int build_csv_record(char *buf, size_t bufsize, struct ast_cdr *cdr)
Definition: cdr_csv.c:211
#define LOG_WARNING
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:187
int errno
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

References ast_cdr::accountcode, accountlogs, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), buf, build_csv_record(), errno, f_lock, file_csv_master, LOG_WARNING, writefile(), and writefile_account().

Referenced by load_module().

◆ load_config()

static int load_config ( int  reload)
static

Definition at line 98 of file cdr_csv.c.

99 {
100  struct ast_config *cfg;
101  struct ast_variable *v;
102  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
103 
104  if (!(cfg = ast_config_load(config, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
105  ast_log(LOG_WARNING, "unable to load config: %s\n", config);
106  return 0;
107  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
108  return 1;
109  }
110 
111  accountlogs = 1;
112  usegmtime = 0;
113  loguniqueid = 0;
114  loguserfield = 0;
115  newcdrcolumns = 0;
116 
117  if (!(v = ast_variable_browse(cfg, "csv"))) {
118  ast_config_destroy(cfg);
119  return 0;
120  }
121 
122  /* compute the location of the csv master file */
124  snprintf(file_csv_master, sizeof(file_csv_master),
127 
128  for (; v; v = v->next) {
129  if (!strcasecmp(v->name, "usegmtime")) {
130  usegmtime = ast_true(v->value);
131  } else if (!strcasecmp(v->name, "accountlogs")) {
132  /* Turn on/off separate files per accountcode. Default is on (as before) */
133  accountlogs = ast_true(v->value);
134  } else if (!strcasecmp(v->name, "loguniqueid")) {
135  loguniqueid = ast_true(v->value);
136  } else if (!strcasecmp(v->name, "loguserfield")) {
138  } else if (!strcasecmp(v->name, "newcdrcolumns")) {
140  }
141 
142  }
143  ast_config_destroy(cfg);
144  return 1;
145 }
#define CSV_MASTER
Definition: cdr_csv.c:50
#define CSV_LOG_DIR
Definition: cdr_csv.c:49
static const char config[]
Definition: cdr_csv.c:60
static int reload(void)
Definition: cdr_csv.c:344
#define ast_config_load(filename, flags)
Load a config file.
@ CONFIG_FLAG_FILEUNCHANGED
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: main/utils.c:2097
Structure used to handle boolean flags.
Definition: utils.h:199
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next

References accountlogs, ast_config_AST_LOG_DIR, ast_config_destroy(), ast_config_load, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_true(), ast_variable_browse(), config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, CSV_LOG_DIR, CSV_MASTER, f_lock, file_csv_master, LOG_WARNING, loguniqueid, loguserfield, ast_variable::name, newcdrcolumns, ast_variable::next, reload(), usegmtime, and ast_variable::value.

Referenced by load_module().

◆ load_module()

static int load_module ( void  )
static

Definition at line 328 of file cdr_csv.c.

329 {
330  int res;
331 
332  if (!load_config(0)) {
334  }
335 
337  ast_log(LOG_ERROR, "Unable to register CSV CDR handling\n");
338  } else {
339  loaded = 1;
340  }
341  return res;
342 }
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:2965
static int csv_log(struct ast_cdr *cdr)
Definition: cdr_csv.c:297
static int loaded
Definition: cdr_csv.c:58
static char * name
Definition: cdr_csv.c:94
static int load_config(int reload)
Definition: cdr_csv.c:98
#define LOG_ERROR
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
const char * description
Definition: module.h:352

References ast_cdr_register(), ast_log, AST_MODULE_LOAD_DECLINE, csv_log(), ast_module_info::description, load_config(), loaded, LOG_ERROR, and name.

◆ reload()

static int reload ( void  )
static

Definition at line 344 of file cdr_csv.c.

345 {
346  if (load_config(1)) {
347  loaded = 1;
348  } else {
349  loaded = 0;
350  ast_log(LOG_WARNING, "No [csv] section in cdr.conf. Unregistering backend.\n");
352  }
353 
354  return 0;
355 }
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:3010

Referenced by load_config().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 318 of file cdr_csv.c.

319 {
320  if (ast_cdr_unregister(name)) {
321  return -1;
322  }
323 
324  loaded = 0;
325  return 0;
326 }

References ast_cdr_unregister(), loaded, and name.

◆ writefile()

static int writefile ( char *  s,
char *  file_path 
)
static

Definition at line 268 of file cdr_csv.c.

269 {
270  FILE *f;
271  /* because of the absolutely unconditional need for the
272  highest reliability possible in writing billing records,
273  we open write and close the log file each time */
274  if (!(f = fopen(file_path, "a"))) {
275  ast_log(LOG_ERROR, "Unable to open file %s : %s\n", file_path, strerror(errno));
276  return -1;
277  }
278  fputs(s, f);
279  fflush(f); /* be particularly anal here */
280  fclose(f);
281 
282  return 0;
283 }

References ast_log, errno, and LOG_ERROR.

Referenced by csv_log(), and writefile_account().

◆ writefile_account()

static int writefile_account ( char *  s,
char *  acc 
)
static

Definition at line 286 of file cdr_csv.c.

287 {
288  char file_account[PATH_MAX];
289  if (strchr(acc, '/') || (acc[0] == '.')) {
290  ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n", acc);
291  return -1;
292  }
293  snprintf(file_account, sizeof(file_account), "%s/%s/%s.csv", ast_config_AST_LOG_DIR,CSV_LOG_DIR, acc);
294  return writefile(s, file_account);
295 }
#define PATH_MAX
Definition: asterisk.h:40

References ast_config_AST_LOG_DIR, ast_log, CSV_LOG_DIR, LOG_WARNING, PATH_MAX, and writefile().

Referenced by csv_log().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Comma Separated Values CDR Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, .requires = "cdr", }
static

Definition at line 344 of file cdr_csv.c.

◆ accountlogs

int accountlogs = 1
static

Definition at line 55 of file cdr_csv.c.

Referenced by csv_log(), and load_config().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 364 of file cdr_csv.c.

◆ config

const char config[] = "cdr.conf"
static

Definition at line 60 of file cdr_csv.c.

Referenced by load_config().

◆ f_lock

ast_mutex_t f_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 96 of file cdr_csv.c.

Referenced by csv_log(), and load_config().

◆ file_csv_master

char file_csv_master[PATH_MAX]
static

Definition at line 61 of file cdr_csv.c.

Referenced by csv_log(), and load_config().

◆ loaded

int loaded = 0
static

Definition at line 58 of file cdr_csv.c.

Referenced by load_module(), load_or_reload_lua_stuff(), and unload_module().

◆ loguniqueid

int loguniqueid = 0
static

Definition at line 56 of file cdr_csv.c.

Referenced by build_csv_record(), and load_config().

◆ loguserfield

int loguserfield = 0
static

Definition at line 57 of file cdr_csv.c.

Referenced by build_csv_record(), and load_config().

◆ name

char* name = "csv"
static

Definition at line 94 of file cdr_csv.c.

Referenced by load_module(), and unload_module().

◆ newcdrcolumns

int newcdrcolumns = 0
static

Definition at line 59 of file cdr_csv.c.

Referenced by build_csv_record(), and load_config().

◆ usegmtime

int usegmtime = 0
static

Definition at line 54 of file cdr_csv.c.

Referenced by append_date(), and load_config().