53#define DATE_FORMAT "%Y-%m-%d %T.%6q" 
   55#define PGSQL_BACKEND_NAME "CEL PGSQL backend" 
   57#define PGSQL_MIN_VERSION_SCHEMA 70300 
   59static char *
config = 
"cel_pgsql.conf";
 
   76#define CEL_SHOW_USERDEF_DEFAULT    0 
   97#define LENGTHEN_BUF(size, var_sql) \ 
  100        if (ast_str_strlen(var_sql) + size + 1 > ast_str_size(var_sql)) { \ 
  101            if (ast_str_make_space(&var_sql, ((ast_str_size(var_sql) + size + 3) / 512 + 1) * 512) != 0) { \ 
  102                ast_log(LOG_ERROR, "Unable to allocate sufficient memory.  Insert CEL '%s:%s' failed.\n", pghostname, table); \ 
  105                AST_RWLIST_UNLOCK(&psql_columns); \ 
 
  111#define LENGTHEN_BUF1(size) \ 
  112    LENGTHEN_BUF(size, sql); 
 
  113#define LENGTHEN_BUF2(size) \ 
  114    LENGTHEN_BUF(size, sql2); 
 
  129    ast_str_set(&conn_info, 0, 
"host=%s port=%s dbname=%s user=%s",
 
 
  165        if (PQstatus(
conn) != CONNECTION_BAD) {
 
  168            pgerror = PQerrorMessage(
conn);
 
  179        char *escapebuf = 
NULL;
 
  182        size_t bufsize = 513;
 
  185        if (!escapebuf || !sql || !sql2) {
 
  186            goto ast_log_cleanup;
 
  192#define SEP (first ? "" : ",") 
  199            if (strcmp(cur->
name, 
"eventtime") == 0) {
 
  200                if (strncmp(cur->
type, 
"int", 3) == 0) {
 
  203                } 
else if (strncmp(cur->
type, 
"float", 5) == 0) {
 
  208                        (
double) record.
event_time.tv_usec / 1000000.0);
 
  216            } 
else if (strcmp(cur->
name, 
"eventtype") == 0) {
 
  217                if (cur->
type[0] == 
'i') {
 
  221                } 
else if (strncmp(cur->
type, 
"float", 5) == 0) {
 
  226                    const char *event_name;
 
  234            } 
else if (strcmp(cur->
name, 
"amaflags") == 0) {
 
  235                if (strncmp(cur->
type, 
"int", 3) == 0) {
 
  246                if (strcmp(cur->
name, 
"userdeftype") == 0) {
 
  248                } 
else if (strcmp(cur->
name, 
"cid_name") == 0) {
 
  250                } 
else if (strcmp(cur->
name, 
"cid_num") == 0) {
 
  252                } 
else if (strcmp(cur->
name, 
"cid_ani") == 0) {
 
  254                } 
else if (strcmp(cur->
name, 
"cid_rdnis") == 0) {
 
  256                } 
else if (strcmp(cur->
name, 
"cid_dnid") == 0) {
 
  258                } 
else if (strcmp(cur->
name, 
"exten") == 0) {
 
  260                } 
else if (strcmp(cur->
name, 
"context") == 0) {
 
  262                } 
else if (strcmp(cur->
name, 
"channame") == 0) {
 
  264                } 
else if (strcmp(cur->
name, 
"appname") == 0) {
 
  266                } 
else if (strcmp(cur->
name, 
"appdata") == 0) {
 
  268                } 
else if (strcmp(cur->
name, 
"accountcode") == 0) {
 
  270                } 
else if (strcmp(cur->
name, 
"peeraccount") == 0) {
 
  272                } 
else if (strcmp(cur->
name, 
"uniqueid") == 0) {
 
  274                } 
else if (strcmp(cur->
name, 
"linkedid") == 0) {
 
  276                } 
else if (strcmp(cur->
name, 
"userfield") == 0) {
 
  278                } 
else if (strcmp(cur->
name, 
"peer") == 0) {
 
  280                } 
else if (strcmp(cur->
name, 
"extra") == 0) {
 
  288                } 
else if (strncmp(cur->
type, 
"int", 3) == 0) {
 
  290                    if (
value && sscanf(
value, 
"%30lld", &whatever) == 1) {
 
  297                } 
else if (strncmp(cur->
type, 
"float", 5) == 0) {
 
  298                    long double whatever;
 
  299                    if (
value && sscanf(
value, 
"%30Lf", &whatever) == 1) {
 
  309                        size_t required_size = strlen(
value) * 2 + 1;
 
  315                        if (required_size > bufsize) {
 
  316                            char *tmpbuf = 
ast_realloc(escapebuf, required_size);
 
  320                                goto ast_log_cleanup;
 
  324                            bufsize = required_size;
 
  344        if (PQstatus(
conn) == CONNECTION_OK) {
 
  349            if (PQstatus(
conn) == CONNECTION_OK) {
 
  353                pgerror = PQerrorMessage(
conn);
 
  359                goto ast_log_cleanup;
 
  363        if (PQresultStatus(
result) != PGRES_COMMAND_OK) {
 
  364            pgerror = PQresultErrorMessage(
result);
 
  369            if (PQstatus(
conn) == CONNECTION_OK) {
 
  374                if (PQresultStatus(
result) != PGRES_COMMAND_OK) {
 
  375                    pgerror = PQresultErrorMessage(
result);
 
  376                    ast_log(
LOG_ERROR, 
"HARD ERROR!  Attempted reconnection failed.  DROPPING CALL RECORD!\n");
 
 
  467        ast_log(
LOG_WARNING,
"PostgreSQL server hostname not specified.  Assuming unix socket connection\n");
 
  478        tmp = 
"asteriskceldb";
 
  571    if (PQstatus(
conn) != CONNECTION_BAD) {
 
  573        char *fname, *ftype, *flen, *fnotnull, *fdef, *tablename, *tmp_tablename;
 
  576        ast_debug(1, 
"Successfully connected to PostgreSQL database.\n");
 
  581        if ((tmp_tablename = strrchr(
table, 
'.'))) {
 
  584            tmp_tablename = 
table;
 
  586        tablename = 
ast_alloca(strlen(tmp_tablename) * 2 + 1);
 
  587        PQescapeStringConn(
conn, tablename, tmp_tablename, strlen(tmp_tablename), 
NULL);
 
  591            lenschema = strlen(
schema);
 
  595            snprintf(sqlcmd, 
sizeof(sqlcmd),
 
  596            "SELECT a.attname, t.typname, a.attlen, a.attnotnull, pg_catalog.pg_get_expr(d.adbin, d.adrelid) adsrc, a.atttypmod " 
  597            "FROM (((pg_catalog.pg_class c INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace " 
  598                     "AND c.relname = '%s' AND n.nspname = %s%s%s) " 
  599                   "INNER JOIN pg_catalog.pg_attribute a ON (" 
  600                       "NOT a.attisdropped) AND a.attnum > 0 AND a.attrelid = c.oid) " 
  601                "INNER JOIN pg_catalog.pg_type t ON t.oid = a.atttypid) " 
  602            "LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid " 
  603              "AND d.adnum = a.attnum " 
  604            "ORDER BY n.nspname, c.relname, attnum",
 
  606                lenschema == 0 ? 
"" : 
"'", lenschema == 0 ? 
"current_schema()" : schemaname, lenschema == 0 ? 
"" : 
"'");
 
  608            snprintf(sqlcmd, 
sizeof(sqlcmd),
 
  609            "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod " 
  610            "FROM pg_class c, pg_type t, pg_attribute a " 
  611            "LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid " 
  612            "AND d.adnum = a.attnum WHERE c.oid = a.attrelid AND a.atttypid = t.oid " 
  613            "AND (a.attnum > 0) AND c.relname = '%s' ORDER BY c.relname, attnum", tablename);
 
  617        if (PQresultStatus(
result) != PGRES_TUPLES_OK) {
 
  618            pgerror = PQresultErrorMessage(
result);
 
  626        for (i = 0; i < rows; i++) {
 
  627            fname = PQgetvalue(
result, i, 0);
 
  628            ftype = PQgetvalue(
result, i, 1);
 
  629            flen = PQgetvalue(
result, i, 2);
 
  630            fnotnull = PQgetvalue(
result, i, 3);
 
  631            fdef = PQgetvalue(
result, i, 4);
 
  632            ast_verb(4, 
"Found column '%s' of type '%s'\n", fname, ftype);
 
  633            cur = 
ast_calloc(1, 
sizeof(*cur) + strlen(fname) + strlen(ftype) + 2);
 
  635                sscanf(flen, 
"%30d", &cur->
len);
 
  636                cur->
name = (
char *)cur + 
sizeof(*cur);
 
  637                cur->
type = (
char *)cur + 
sizeof(*cur) + strlen(fname) + 1;
 
  638                strcpy(cur->
name, fname);
 
  639                strcpy(cur->
type, ftype);
 
  640                if (*fnotnull == 
't') {
 
  655        pgerror = PQerrorMessage(
conn);
 
 
struct sla_ringing_trunk * first
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_realloc(p, len)
A wrapper for realloc()
#define ast_strdup(str)
A wrapper for strdup()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_malloc(len)
A wrapper for malloc()
int ast_cel_backend_unregister(const char *name)
Unregister a CEL backend.
@ AST_CEL_USER_DEFINED
a user-defined event, the event name field should be set
int ast_cel_fill_record(const struct ast_event *event, struct ast_cel_event_record *r)
Fill in an ast_cel_event_record from a CEL event.
#define AST_CEL_EVENT_RECORD_VERSION
struct ABI version
int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback)
Register a CEL backend.
#define LENGTHEN_BUF2(size)
static int process_my_load_module(struct ast_config *cfg)
#define CEL_SHOW_USERDEF_DEFAULT
show_user_def is off by default
static void pgsql_reconnect(void)
static int my_load_module(int reload)
static int my_unload_module(void)
#define PGSQL_MIN_VERSION_SCHEMA
#define PGSQL_BACKEND_NAME
static ast_mutex_t pgsql_lock
static unsigned char cel_show_user_def
static void pgsql_log(struct ast_event *event)
static int load_module(void)
static int unload_module(void)
#define LENGTHEN_BUF1(size)
static char version[AST_MAX_EXTENSION]
General Asterisk PBX channel definitions.
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
@ CONFIG_FLAG_FILEUNCHANGED
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Support for logging to various files, console and syslog Configuration in file logger....
#define DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_RWLIST_REMOVE_HEAD
#define AST_RWLIST_TRAVERSE
#define AST_RWLIST_INSERT_TAIL
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
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...
#define ast_mutex_unlock(a)
#define ast_mutex_lock(a)
#define AST_MUTEX_DEFINE_STATIC(mutex)
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_EXTENDED
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Options provided by main asterisk program.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
size_t attribute_pure ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Helper struct for getting the fields out of a CEL event.
const char * caller_id_dnid
const char * application_data
const char * account_code
const char * caller_id_rdnis
const char * caller_id_num
const char * channel_name
const char * peer_account
enum ast_cel_event_type event_type
const char * user_defined_name
const char * application_name
struct timeval event_time
uint32_t version
struct ABI version
const char * caller_id_ani
const char * caller_id_name
Structure used to handle boolean flags.
Support for dynamic strings.
Structure for variables, used for configurations and for channel variables.
struct columns::@114 list