Wed Jan 8 2020 09:49:59

Asterisk developer's documentation


cdr_odbc.c File Reference

ODBC CDR Backend. More...

#include "asterisk.h"
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/module.h"
#include "asterisk/res_odbc.h"

Go to the source code of this file.

Macros

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

Enumerations

enum  {
  CONFIG_LOGUNIQUEID = 1 << 0, CONFIG_USEGMTIME = 1 << 1, CONFIG_DISPOSITIONSTRING = 1 << 2, CONFIG_HRTIME = 1 << 3,
  CONFIG_REGISTERED = 1 << 4
}
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static SQLHSTMT execute_cb (struct odbc_obj *obj, void *data)
 
static int load_module (void)
 
static int odbc_load_module (int reload)
 
static int odbc_log (struct ast_cdr *cdr)
 
static int reload (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "ODBC 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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, }
 
static struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_flags config = { 0 }
 
static const char config_file [] = "cdr_odbc.conf"
 
static char * dsn = NULL
 
static const char name [] = "ODBC"
 
static char * table = NULL
 

Detailed Description

ODBC CDR Backend.

Author
Brian K. West brian.nosp@m.@bkw.nosp@m..org

See also:

Definition in file cdr_odbc.c.

Macro Definition Documentation

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

Definition at line 46 of file cdr_odbc.c.

Referenced by execute_cb().

Enumeration Type Documentation

anonymous enum
Enumerator
CONFIG_LOGUNIQUEID 
CONFIG_USEGMTIME 
CONFIG_DISPOSITIONSTRING 
CONFIG_HRTIME 
CONFIG_REGISTERED 

Definition at line 52 of file cdr_odbc.c.

Function Documentation

static void __reg_module ( void  )
static

Definition at line 298 of file cdr_odbc.c.

static void __unreg_module ( void  )
static

Definition at line 298 of file cdr_odbc.c.

static SQLHSTMT execute_cb ( struct odbc_obj obj,
void *  data 
)
static

Definition at line 62 of file cdr_odbc.c.

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_disp2str(), ast_localtime(), ast_strftime(), ast_test_flag, ast_tvdiff_us(), ast_tvzero(), ast_verb, ast_cdr::billsec, ast_cdr::channel, ast_cdr::clid, odbc_obj::con, CONFIG_DISPOSITIONSTRING, CONFIG_HRTIME, CONFIG_LOGUNIQUEID, CONFIG_USEGMTIME, DATE_FORMAT, 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::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.

Referenced by odbc_log().

63 {
64  struct ast_cdr *cdr = data;
65  SQLRETURN ODBC_res;
66  char sqlcmd[2048] = "", timestr[128];
67  struct ast_tm tm;
68  SQLHSTMT stmt;
69 
70  ast_localtime(&cdr->start, &tm, ast_test_flag(&config, CONFIG_USEGMTIME) ? "GMT" : NULL);
71  ast_strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
72 
74  snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
75  "(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,"
76  "lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) "
77  "VALUES ({ts '%s'},?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", table, timestr);
78  } else {
79  snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
80  "(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,"
81  "duration,billsec,disposition,amaflags,accountcode) "
82  "VALUES ({ts '%s'},?,?,?,?,?,?,?,?,?,?,?,?,?)", table, timestr);
83  }
84 
85  ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
86 
87  if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
88  ast_verb(11, "cdr_odbc: Failure in AllocStatement %d\n", ODBC_res);
89  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
90  return NULL;
91  }
92 
93  SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->clid), 0, cdr->clid, 0, NULL);
94  SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->src), 0, cdr->src, 0, NULL);
95  SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dst), 0, cdr->dst, 0, NULL);
96  SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dcontext), 0, cdr->dcontext, 0, NULL);
97  SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->channel), 0, cdr->channel, 0, NULL);
98  SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dstchannel), 0, cdr->dstchannel, 0, NULL);
99  SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastapp), 0, cdr->lastapp, 0, NULL);
100  SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastdata), 0, cdr->lastdata, 0, NULL);
101 
103  double hrbillsec = 0.0;
104  double hrduration;
105 
106  if (!ast_tvzero(cdr->answer)) {
107  hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0;
108  }
109  hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0;
110 
111  SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_FLOAT, 0, 0, &hrduration, 0, NULL);
112  SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_FLOAT, 0, 0, &hrbillsec, 0, NULL);
113  } else {
114  SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL);
115  SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
116  }
117 
119  SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ast_cdr_disp2str(cdr->disposition)) + 1, 0, ast_cdr_disp2str(cdr->disposition), 0, NULL);
120  else
121  SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->disposition, 0, NULL);
122  SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL);
123  SQLBindParameter(stmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->accountcode), 0, cdr->accountcode, 0, NULL);
124 
126  SQLBindParameter(stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->uniqueid), 0, cdr->uniqueid, 0, NULL);
127  SQLBindParameter(stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->userfield), 0, cdr->userfield, 0, NULL);
128  }
129 
130  ODBC_res = SQLExecDirect(stmt, (unsigned char *)sqlcmd, SQL_NTS);
131 
132  if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
133  ast_verb(11, "cdr_odbc: Error in ExecDirect: %d\n", ODBC_res);
134  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
135  return NULL;
136  }
137 
138  return stmt;
139 }
SQLHDBC con
Definition: res_odbc.h:48
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:114
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:94
static struct ast_flags config
Definition: cdr_odbc.c:60
#define ast_test_flag(p, flag)
Definition: utils.h:63
long int billsec
Definition: cdr.h:108
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:90
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:1570
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:100
char uniqueid[150]
Definition: cdr.h:121
#define ast_verb(level,...)
Definition: logger.h:243
static char * table
Definition: cdr_odbc.c:50
#define DATE_FORMAT
Definition: cdr_odbc.c:46
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:98
long int amaflags
Definition: cdr.h:112
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:88
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:92
struct timeval answer
Definition: cdr.h:102
Responsible for call detail data.
Definition: cdr.h:82
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:96
struct timeval start
Definition: cdr.h:100
long int duration
Definition: cdr.h:106
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:2351
char src[AST_MAX_EXTENSION]
Definition: cdr.h:86
struct timeval end
Definition: cdr.h:104
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:70
long int disposition
Definition: cdr.h:110
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:84
char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:959
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:125
static int load_module ( void  )
static

Definition at line 267 of file cdr_odbc.c.

References odbc_load_module().

268 {
269  return odbc_load_module(0);
270 }
static int odbc_load_module(int reload)
Definition: cdr_odbc.c:167
static int odbc_load_module ( int  reload)
static

Definition at line 167 of file cdr_odbc.c.

References ast_cdr_register(), ast_cdr_unregister(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_debug, ast_free, ast_log(), AST_MODULE_LOAD_DECLINE, ast_set_flag, ast_strdup, ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_DISPOSITIONSTRING, CONFIG_FLAG_FILEUNCHANGED, CONFIG_HRTIME, CONFIG_LOGUNIQUEID, CONFIG_REGISTERED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, CONFIG_USEGMTIME, ast_module_info::description, LOG_ERROR, LOG_WARNING, odbc_log(), and var.

Referenced by load_module(), and reload().

168 {
169  int res = 0;
170  struct ast_config *cfg;
171  struct ast_variable *var;
172  const char *tmp;
173  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
174 
175  do {
176  cfg = ast_config_load(config_file, config_flags);
177  if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
178  ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config_file);
180  break;
181  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
182  break;
183 
184  var = ast_variable_browse(cfg, "global");
185  if (!var) {
186  /* nothing configured */
187  break;
188  }
189 
190  if ((tmp = ast_variable_retrieve(cfg, "global", "dsn")) == NULL) {
191  ast_log(LOG_WARNING, "cdr_odbc: dsn not specified. Assuming asteriskdb\n");
192  tmp = "asteriskdb";
193  }
194  if (dsn)
195  ast_free(dsn);
196  dsn = ast_strdup(tmp);
197  if (dsn == NULL) {
198  res = -1;
199  break;
200  }
201 
202  if (((tmp = ast_variable_retrieve(cfg, "global", "dispositionstring"))) && ast_true(tmp))
204  else
206 
207  if (((tmp = ast_variable_retrieve(cfg, "global", "loguniqueid"))) && ast_true(tmp)) {
209  ast_debug(1, "cdr_odbc: Logging uniqueid\n");
210  } else {
212  ast_debug(1, "cdr_odbc: Not logging uniqueid\n");
213  }
214 
215  if (((tmp = ast_variable_retrieve(cfg, "global", "usegmtime"))) && ast_true(tmp)) {
217  ast_debug(1, "cdr_odbc: Logging in GMT\n");
218  } else {
220  ast_debug(1, "cdr_odbc: Logging in local time\n");
221  }
222 
223  if (((tmp = ast_variable_retrieve(cfg, "global", "hrtime"))) && ast_true(tmp)) {
225  ast_debug(1, "cdr_odbc: Logging billsec and duration fields as floats\n");
226  } else {
228  ast_debug(1, "cdr_odbc: Logging billsec and duration fields as integers\n");
229  }
230 
231  if ((tmp = ast_variable_retrieve(cfg, "global", "table")) == NULL) {
232  ast_log(LOG_WARNING, "cdr_odbc: table not specified. Assuming cdr\n");
233  tmp = "cdr";
234  }
235  if (table)
236  ast_free(table);
237  table = ast_strdup(tmp);
238  if (table == NULL) {
239  res = -1;
240  break;
241  }
242 
243  ast_verb(3, "cdr_odbc: dsn is %s\n", dsn);
244  ast_verb(3, "cdr_odbc: table is %s\n", table);
245 
248  if (res) {
249  ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n");
250  } else {
252  }
253  }
254  } while (0);
255 
256  if (ast_test_flag(&config, CONFIG_REGISTERED) && (!cfg || dsn == NULL || table == NULL)) {
259  }
260 
261  if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED && cfg != CONFIG_STATUS_FILEINVALID) {
262  ast_config_destroy(cfg);
263  }
264  return res;
265 }
const char * description
Definition: module.h:234
static const char config_file[]
Definition: cdr_odbc.c:49
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
#define ast_strdup(a)
Definition: astmm.h:109
static struct ast_flags config
Definition: cdr_odbc.c:60
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
#define ast_verb(level,...)
Definition: logger.h:243
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static int reload(void)
Definition: cdr_odbc.c:288
static char * table
Definition: cdr_odbc.c:50
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:130
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static int odbc_log(struct ast_cdr *cdr)
Definition: cdr_odbc.c:142
#define LOG_ERROR
Definition: logger.h:155
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static const char name[]
#define ast_free(a)
Definition: astmm.h:97
static char * dsn
Definition: cdr_odbc.c:50
Structure used to handle boolean flags.
Definition: utils.h:200
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
void ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:165
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
static int odbc_log ( struct ast_cdr cdr)
static

Definition at line 142 of file cdr_odbc.c.

References ast_log(), ast_odbc_direct_execute(), ast_odbc_release_obj(), ast_odbc_request_obj, execute_cb(), LOG_ERROR, and LOG_WARNING.

Referenced by odbc_load_module().

143 {
144  struct odbc_obj *obj = ast_odbc_request_obj(dsn, 0);
145  SQLHSTMT stmt;
146 
147  if (!obj) {
148  ast_log(LOG_ERROR, "Unable to retrieve database handle. CDR failed.\n");
149  return -1;
150  }
151 
152  stmt = ast_odbc_direct_execute(obj, execute_cb, cdr);
153  if (stmt) {
154  SQLLEN rows = 0;
155 
156  SQLRowCount(stmt, &rows);
157  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
158 
159  if (rows == 0)
160  ast_log(LOG_WARNING, "CDR successfully ran, but inserted 0 rows?\n");
161  } else
162  ast_log(LOG_ERROR, "CDR direct execute failed\n");
164  return 0;
165 }
#define LOG_WARNING
Definition: logger.h:144
static SQLHSTMT execute_cb(struct odbc_obj *obj, void *data)
Definition: cdr_odbc.c:62
ODBC container.
Definition: res_odbc.h:46
#define LOG_ERROR
Definition: logger.h:155
SQLHSTMT ast_odbc_direct_execute(struct odbc_obj *obj, SQLHSTMT(*exec_cb)(struct odbc_obj *obj, void *data), void *data)
Executes an non prepared statement and returns the resulting statement handle.
Definition: res_odbc.c:594
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_odbc_request_obj(a, b)
Definition: res_odbc.h:123
static char * dsn
Definition: cdr_odbc.c:50
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:1112
static int reload ( void  )
static

Definition at line 288 of file cdr_odbc.c.

References odbc_load_module().

289 {
290  return odbc_load_module(1);
291 }
static int odbc_load_module(int reload)
Definition: cdr_odbc.c:167
static int unload_module ( void  )
static

Definition at line 272 of file cdr_odbc.c.

References ast_cdr_unregister(), ast_free, and ast_verb.

273 {
275 
276  if (dsn) {
277  ast_verb(11, "cdr_odbc: free dsn\n");
278  ast_free(dsn);
279  }
280  if (table) {
281  ast_verb(11, "cdr_odbc: free table\n");
282  ast_free(table);
283  }
284 
285  return 0;
286 }
#define ast_verb(level,...)
Definition: logger.h:243
static char * table
Definition: cdr_odbc.c:50
static const char name[]
#define ast_free(a)
Definition: astmm.h:97
static char * dsn
Definition: cdr_odbc.c:50
void ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:165

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "ODBC 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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, }
static

Definition at line 298 of file cdr_odbc.c.

Definition at line 298 of file cdr_odbc.c.

struct ast_flags config = { 0 }
static

Definition at line 60 of file cdr_odbc.c.

const char config_file[] = "cdr_odbc.conf"
static

Definition at line 49 of file cdr_odbc.c.

char* dsn = NULL
static
const char name[] = "ODBC"
static

Definition at line 48 of file cdr_odbc.c.