Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
app_mysql.c File Reference

MYSQL dialplan application. More...

#include "asterisk.h"
#include <mysql/mysql.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/linkedlists.h"
#include "asterisk/chanvars.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
#include "asterisk/config.h"
Include dependency graph for app_mysql.c:

Go to the source code of this file.

Data Structures

struct  ast_MYSQL_id
 
struct  MYSQLidshead
 

Macros

#define AST_MYSQL_ID_CONNID   1
 
#define AST_MYSQL_ID_DUMMY   0
 
#define AST_MYSQL_ID_FETCHID   3
 
#define AST_MYSQL_ID_RESID   2
 
#define EXTRA_LOG   0
 
#define MYSQL_CONFIG   "app_mysql.conf"
 
#define MYSQL_CONFIG_OLD   "mysql.conf"
 

Enumerations

enum  { NULLSTRING, NULLVALUE, EMPTYSTRING }
 

Functions

static int add_identifier (struct ast_channel *chan, int identifier_type, void *data)
 
static int add_identifier_and_set_asterisk_int (struct ast_channel *chan, char *varname, int identifier_type, void *data)
 
static int aMYSQL_clear (struct ast_channel *chan, const char *data)
 
static int aMYSQL_connect (struct ast_channel *chan, const char *data)
 
static int aMYSQL_disconnect (struct ast_channel *chan, const char *data)
 
static int aMYSQL_fetch (struct ast_channel *chan, const char *data)
 
static int aMYSQL_nextresult (struct ast_channel *chan, const char *data)
 
static int aMYSQL_query (struct ast_channel *chan, const char *data)
 
static int aMYSQL_set (struct ast_channel *chan, const char *data)
 
 AST_MODULE_INFO_STANDARD_DEPRECATED (ASTERISK_GPL_KEY, "Simple Mysql Interface")
 
static int del_identifier (int identifier, int identifier_type)
 
static void * find_identifier (int identifier, int identifier_type)
 
static int load_module (void)
 Load the module. More...
 
static void mysql_ds_destroy (void *data)
 
static void mysql_ds_fixup (void *data, struct ast_channel *oldchan, struct ast_channel *newchan)
 
static int MYSQL_exec (struct ast_channel *chan, const char *data)
 
static int safe_scan_int (char **data, char *delim, int def)
 
static int set_asterisk_int (struct ast_channel *chan, char *varname, int id)
 
static int unload_module (void)
 

Variables

struct MYSQLidshead _mysql_ids_head
 
static ast_mutex_t _mysql_mutex = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static const char app [] = "MYSQL"
 
struct ast_MYSQL_idast_MYSQL_id
 
static int autoclear = 0
 
static const char descrip []
 
static const struct ast_datastore_info mysql_ds_info
 
enum { ... }  nullvalue = NULLSTRING
 
static const char synopsis [] = "Do several mySQLy things"
 

Detailed Description

MYSQL dialplan application.

Definition in file app_mysql.c.

Macro Definition Documentation

◆ AST_MYSQL_ID_CONNID

#define AST_MYSQL_ID_CONNID   1

◆ AST_MYSQL_ID_DUMMY

#define AST_MYSQL_ID_DUMMY   0

Definition at line 108 of file app_mysql.c.

◆ AST_MYSQL_ID_FETCHID

#define AST_MYSQL_ID_FETCHID   3

Definition at line 111 of file app_mysql.c.

◆ AST_MYSQL_ID_RESID

#define AST_MYSQL_ID_RESID   2

◆ EXTRA_LOG

#define EXTRA_LOG   0

Definition at line 58 of file app_mysql.c.

◆ MYSQL_CONFIG

#define MYSQL_CONFIG   "app_mysql.conf"

Definition at line 106 of file app_mysql.c.

Referenced by load_module().

◆ MYSQL_CONFIG_OLD

#define MYSQL_CONFIG_OLD   "mysql.conf"

Definition at line 107 of file app_mysql.c.

Referenced by load_module().

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
NULLSTRING 
NULLVALUE 
EMPTYSTRING 

Definition at line 60 of file app_mysql.c.

Function Documentation

◆ add_identifier()

static int add_identifier ( struct ast_channel chan,
int  identifier_type,
void *  data 
)
static

Definition at line 211 of file app_mysql.c.

References _mysql_ids_head, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_malloc, ast_MYSQL_id::data, ast_MYSQL_id::entries, ast_MYSQL_id::identifier, ast_MYSQL_id::identifier_type, LOG_WARNING, NULL, and ast_MYSQL_id::owner.

Referenced by add_identifier_and_set_asterisk_int().

212 {
213  struct ast_MYSQL_id *i = NULL, *j = NULL;
214  struct MYSQLidshead *headp = &_mysql_ids_head;
215  int maxidentifier = 0;
216 
217  if (AST_LIST_LOCK(headp)) {
218  ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
219  return -1;
220  } else {
221  i = ast_malloc(sizeof(*i));
222  AST_LIST_TRAVERSE(headp, j, entries) {
223  if (j->identifier > maxidentifier) {
224  maxidentifier = j->identifier;
225  }
226  }
227  i->identifier = maxidentifier + 1;
228  i->identifier_type = identifier_type;
229  i->data = data;
230  i->owner = chan;
231  AST_LIST_INSERT_HEAD(headp, i, entries);
232  AST_LIST_UNLOCK(headp);
233  }
234  return i->identifier;
235 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int identifier
Definition: app_mysql.c:127
struct MYSQLidshead _mysql_ids_head
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
struct ast_channel * owner
Definition: app_mysql.c:125
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
void * data
Definition: app_mysql.c:128
int identifier_type
Definition: app_mysql.c:126

◆ add_identifier_and_set_asterisk_int()

static int add_identifier_and_set_asterisk_int ( struct ast_channel chan,
char *  varname,
int  identifier_type,
void *  data 
)
static

Definition at line 277 of file app_mysql.c.

References add_identifier(), and set_asterisk_int().

Referenced by aMYSQL_connect(), aMYSQL_nextresult(), and aMYSQL_query().

278 {
279  return set_asterisk_int(chan, varname, add_identifier(chan, identifier_type, data));
280 }
static int set_asterisk_int(struct ast_channel *chan, char *varname, int id)
Definition: app_mysql.c:266
static int add_identifier(struct ast_channel *chan, int identifier_type, void *data)
Definition: app_mysql.c:211

◆ aMYSQL_clear()

static int aMYSQL_clear ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 525 of file app_mysql.c.

References ast_log, AST_MYSQL_ID_RESID, ast_strdupa, del_identifier(), find_identifier(), id, LOG_WARNING, NULL, parse(), safe_scan_int(), and strsep().

Referenced by MYSQL_exec().

526 {
527  MYSQL_RES *mysqlres;
528 
529  int id;
530  char *parse = ast_strdupa(data);
531  strsep(&parse, " "); /* eat the first token, we already know it :P */
532  id = safe_scan_int(&parse, " \n", -1);
533  if ((mysqlres = find_identifier(id, AST_MYSQL_ID_RESID)) == NULL) {
534  ast_log(LOG_WARNING, "Invalid result identifier %d passed in aMYSQL_clear\n", id);
535  } else {
536  mysql_free_result(mysqlres);
538  }
539 
540  return 0;
541 }
static int safe_scan_int(char **data, char *delim, int def)
Definition: app_mysql.c:282
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
static void * find_identifier(int identifier, int identifier_type)
Definition: app_mysql.c:185
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int del_identifier(int identifier, int identifier_type)
Definition: app_mysql.c:237
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
char * strsep(char **str, const char *delims)
enum queue_result id
Definition: app_queue.c:1507
#define AST_MYSQL_ID_RESID
Definition: app_mysql.c:110

◆ aMYSQL_connect()

static int aMYSQL_connect ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 321 of file app_mysql.c.

References add_identifier_and_set_asterisk_int(), args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log, AST_MYSQL_ID_CONNID, AST_NONSTANDARD_APP_ARGS, ast_strdupa, dbcharset, dbhost, dbname, dbpass, dbuser, LOG_WARNING, mysql, NULL, parse(), pbx_builtin_getvar_helper(), and timeout.

Referenced by MYSQL_exec().

322 {
324  AST_APP_ARG(connect);
325  AST_APP_ARG(connid);
331  );
332  MYSQL *mysql;
333  int timeout;
334  const char *ctimeout;
335  unsigned int port = 0;
336  char *port_str;
337  char *parse = ast_strdupa(data);
338 
339  AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
340 
341  if (args.argc < 6) {
342  ast_log(LOG_WARNING, "MYSQL_connect is missing some arguments\n");
343  return -1;
344  }
345 
346  if (!(mysql = mysql_init(NULL))) {
347  ast_log(LOG_WARNING, "mysql_init returned NULL\n");
348  return -1;
349  }
350 
351  ctimeout = pbx_builtin_getvar_helper(chan, "MYSQL_TIMEOUT");
352  if (ctimeout && sscanf(ctimeout, "%30d", &timeout) == 1) {
353  mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&timeout);
354  }
355  if(args.dbcharset && strlen(args.dbcharset) > 2){
356  char set_names[255];
357  char statement[512];
358  snprintf(set_names, sizeof(set_names), "SET NAMES %s", args.dbcharset);
359  mysql_real_escape_string(mysql, statement, set_names, sizeof(set_names));
360  mysql_options(mysql, MYSQL_INIT_COMMAND, set_names);
361  mysql_options(mysql, MYSQL_SET_CHARSET_NAME, args.dbcharset);
362  }
363 
364  if ((port_str = strchr(args.dbhost, ':'))) {
365  *port_str++ = '\0';
366  if (sscanf(port_str, "%u", &port) != 1) {
367  ast_log(LOG_WARNING, "Invalid port: '%s'\n", port_str);
368  port = 0;
369  }
370  }
371 
372  if (!mysql_real_connect(mysql, args.dbhost, args.dbuser, args.dbpass, args.dbname, port, NULL,
373 #ifdef CLIENT_MULTI_STATEMENTS
374  CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS
375 #elif defined(CLIENT_MULTI_QUERIES)
376  CLIENT_MULTI_QUERIES
377 #else
378  0
379 #endif
380  )) {
381  ast_log(LOG_WARNING, "mysql_real_connect(mysql,%s,%s,dbpass,%s,...) failed(%d): %s\n",
382  args.dbhost, args.dbuser, args.dbname, mysql_errno(mysql), mysql_error(mysql));
383  return -1;
384  }
385 
387  return 0;
388 }
#define LOG_WARNING
Definition: logger.h:274
static int timeout
Definition: cdr_mysql.c:86
const char * args
#define NULL
Definition: resample.c:96
static char dbpass[MAX_DB_OPTION_SIZE]
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
static struct ast_str * dbcharset
Definition: cdr_mysql.c:77
static int add_identifier_and_set_asterisk_int(struct ast_channel *chan, char *varname, int identifier_type, void *data)
Definition: app_mysql.c:277
#define ast_log
Definition: astobj2.c:42
#define AST_MYSQL_ID_CONNID
Definition: app_mysql.c:109
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
static struct ast_str * dbname
Definition: cdr_mysql.c:77
static struct ast_str * dbuser
Definition: cdr_mysql.c:77
static char dbhost[MAX_DB_OPTION_SIZE]
static MYSQL mysql
Definition: cdr_mysql.c:109
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ aMYSQL_disconnect()

static int aMYSQL_disconnect ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 543 of file app_mysql.c.

References ast_log, AST_MYSQL_ID_CONNID, ast_strdupa, del_identifier(), find_identifier(), id, LOG_WARNING, mysql, NULL, parse(), safe_scan_int(), and strsep().

Referenced by MYSQL_exec().

544 {
545  MYSQL *mysql;
546  int id;
547  char *parse = ast_strdupa(data);
548  strsep(&parse, " "); /* eat the first token, we already know it :P */
549 
550  id = safe_scan_int(&parse, " \n", -1);
551  if ((mysql = find_identifier(id, AST_MYSQL_ID_CONNID)) == NULL) {
552  ast_log(LOG_WARNING, "Invalid connection identifier %d passed in aMYSQL_disconnect\n", id);
553  } else {
554  mysql_close(mysql);
556  }
557 
558  return 0;
559 }
static int safe_scan_int(char **data, char *delim, int def)
Definition: app_mysql.c:282
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
static void * find_identifier(int identifier, int identifier_type)
Definition: app_mysql.c:185
#define ast_log
Definition: astobj2.c:42
#define AST_MYSQL_ID_CONNID
Definition: app_mysql.c:109
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int del_identifier(int identifier, int identifier_type)
Definition: app_mysql.c:237
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
char * strsep(char **str, const char *delims)
enum queue_result id
Definition: app_queue.c:1507
static MYSQL mysql
Definition: cdr_mysql.c:109

◆ aMYSQL_fetch()

static int aMYSQL_fetch ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 473 of file app_mysql.c.

References args, AST_APP_ARG, ast_debug, AST_DECLARE_APP_ARGS, ast_log, AST_MYSQL_ID_RESID, AST_NONSTANDARD_APP_ARGS, ast_strdupa, EMPTYSTRING, find_identifier(), LOG_WARNING, NULL, NULLSTRING, nullvalue, parse(), pbx_builtin_setvar_helper(), set_asterisk_int(), and strsep().

Referenced by MYSQL_exec().

474 {
475  MYSQL_RES *mysqlres;
476  MYSQL_ROW mysqlrow;
478  AST_APP_ARG(fetch);
479  AST_APP_ARG(resultvar);
480  AST_APP_ARG(fetchid);
481  AST_APP_ARG(vars);
482  );
483  char *s5, *parse;
484  int resultid = -1, numFields, j;
485 
486  parse = ast_strdupa(data);
487  AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
488  sscanf(args.fetchid, "%30d", &resultid);
489 
490  if (args.resultvar && (resultid >= 0) ) {
491  if ((mysqlres = find_identifier(resultid, AST_MYSQL_ID_RESID)) != NULL) {
492  /* Grab the next row */
493  if ((mysqlrow = mysql_fetch_row(mysqlres)) != NULL) {
494  numFields = mysql_num_fields(mysqlres);
495  for (j = 0; j < numFields; j++) {
496  s5 = strsep(&args.vars, " ");
497  if (s5 == NULL) {
498  ast_log(LOG_WARNING, "ast_MYSQL_fetch: More fields (%d) than variables (%d)\n", numFields, j);
499  break;
500  }
501 
502  pbx_builtin_setvar_helper(chan, s5, mysqlrow[j] ? mysqlrow[j] :
503  nullvalue == NULLSTRING ? "NULL" :
504  nullvalue == EMPTYSTRING ? "" :
505  NULL);
506  }
507  ast_debug(5, "ast_MYSQL_fetch: numFields=%d\n", numFields);
508  set_asterisk_int(chan, args.resultvar, 1); /* try more rows */
509  } else {
510  ast_debug(5, "ast_MYSQL_fetch : EOF\n");
511  set_asterisk_int(chan, args.resultvar, 0); /* no more rows */
512  }
513  return 0;
514  } else {
515  set_asterisk_int(chan, args.resultvar, 0);
516  ast_log(LOG_WARNING, "aMYSQL_fetch: Invalid result identifier %d passed\n", resultid);
517  }
518  } else {
519  ast_log(LOG_WARNING, "aMYSQL_fetch: missing some arguments\n");
520  }
521 
522  return -1;
523 }
#define LOG_WARNING
Definition: logger.h:274
static int set_asterisk_int(struct ast_channel *chan, char *varname, int id)
Definition: app_mysql.c:266
const char * args
#define NULL
Definition: resample.c:96
static void * find_identifier(int identifier, int identifier_type)
Definition: app_mysql.c:185
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
enum @0 nullvalue
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
char * strsep(char **str, const char *delims)
#define AST_MYSQL_ID_RESID
Definition: app_mysql.c:110
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ aMYSQL_nextresult()

static int aMYSQL_nextresult ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 432 of file app_mysql.c.

References add_identifier_and_set_asterisk_int(), args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log, AST_MYSQL_ID_CONNID, AST_MYSQL_ID_RESID, AST_NONSTANDARD_APP_ARGS, ast_strdupa, find_identifier(), LOG_WARNING, mysql, and parse().

Referenced by MYSQL_exec().

433 {
434  MYSQL *mysql;
435  MYSQL_RES *mysqlres;
437  AST_APP_ARG(nextresult);
438  AST_APP_ARG(resultid);
439  AST_APP_ARG(connid);
440  );
441  int connid = -1;
442  char *parse = ast_strdupa(data);
443 
444  AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
445  sscanf(args.connid, "%30d", &connid);
446 
447  if (args.argc != 3 || connid <= 0) {
448  ast_log(LOG_WARNING, "missing some arguments\n");
449  return -1;
450  }
451 
452  if (!(mysql = find_identifier(connid, AST_MYSQL_ID_CONNID))) {
453  ast_log(LOG_WARNING, "Invalid connection identifier %d passed in aMYSQL_query\n", connid);
454  return -1;
455  }
456 
457  if (mysql_more_results(mysql)) {
458  mysql_next_result(mysql);
459  if ((mysqlres = mysql_store_result(mysql))) {
461  return 0;
462  } else if (!mysql_field_count(mysql)) {
463  return 0;
464  } else
465  ast_log(LOG_WARNING, "mysql_store_result() failed on storing next_result\n");
466  } else
467  ast_log(LOG_WARNING, "mysql_more_results() result set has no more results\n");
468 
469  return 0;
470 }
#define LOG_WARNING
Definition: logger.h:274
const char * args
static void * find_identifier(int identifier, int identifier_type)
Definition: app_mysql.c:185
static int add_identifier_and_set_asterisk_int(struct ast_channel *chan, char *varname, int identifier_type, void *data)
Definition: app_mysql.c:277
#define ast_log
Definition: astobj2.c:42
#define AST_MYSQL_ID_CONNID
Definition: app_mysql.c:109
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define AST_MYSQL_ID_RESID
Definition: app_mysql.c:110
static MYSQL mysql
Definition: cdr_mysql.c:109
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ aMYSQL_query()

static int aMYSQL_query ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 390 of file app_mysql.c.

References add_identifier_and_set_asterisk_int(), args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log, AST_MYSQL_ID_CONNID, AST_MYSQL_ID_RESID, AST_NONSTANDARD_APP_ARGS, ast_strdupa, find_identifier(), LOG_WARNING, mysql, and parse().

Referenced by MYSQL_exec().

391 {
393  AST_APP_ARG(query);
394  AST_APP_ARG(resultid);
395  AST_APP_ARG(connid);
396  AST_APP_ARG(sql);
397  );
398  MYSQL *mysql;
399  MYSQL_RES *mysqlres;
400  int connid;
401  int mysql_query_res;
402  char *parse = ast_strdupa(data);
403 
404  AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
405 
406  if (args.argc != 4 || (connid = atoi(args.connid)) == 0) {
407  ast_log(LOG_WARNING, "missing some arguments\n");
408  return -1;
409  }
410 
411  if (!(mysql = find_identifier(connid, AST_MYSQL_ID_CONNID))) {
412  ast_log(LOG_WARNING, "Invalid connection identifier %s passed in aMYSQL_query\n", args.connid);
413  return -1;
414  }
415 
416  if ((mysql_query_res = mysql_query(mysql, args.sql)) != 0) {
417  ast_log(LOG_WARNING, "aMYSQL_query: mysql_query failed. Error: %s\n", mysql_error(mysql));
418  return -1;
419  }
420 
421  if ((mysqlres = mysql_store_result(mysql))) {
423  return 0;
424  } else if (!mysql_field_count(mysql)) {
425  return 0;
426  } else
427  ast_log(LOG_WARNING, "mysql_store_result() failed on query %s\n", args.sql);
428 
429  return -1;
430 }
#define LOG_WARNING
Definition: logger.h:274
const char * args
static void * find_identifier(int identifier, int identifier_type)
Definition: app_mysql.c:185
static int add_identifier_and_set_asterisk_int(struct ast_channel *chan, char *varname, int identifier_type, void *data)
Definition: app_mysql.c:277
#define ast_log
Definition: astobj2.c:42
#define AST_MYSQL_ID_CONNID
Definition: app_mysql.c:109
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define AST_MYSQL_ID_RESID
Definition: app_mysql.c:110
static MYSQL mysql
Definition: cdr_mysql.c:109
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ aMYSQL_set()

static int aMYSQL_set ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 295 of file app_mysql.c.

References args, ast_alloca, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_NONSTANDARD_APP_ARGS, ast_strdupa, parse(), pbx_builtin_setvar_helper(), tmp(), value, and var.

Referenced by MYSQL_exec().

296 {
297  char *var, *tmp, *parse;
299  AST_APP_ARG(set);
300  AST_APP_ARG(variable);
302  );
303 
304  parse = ast_strdupa(data);
305  AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
306 
307  if (args.argc == 3) {
308  var = ast_alloca(6 + strlen(args.variable) + 1);
309  sprintf(var, "MYSQL_%s", args.variable);
310 
311  /* Make the parameter case-insensitive */
312  for (tmp = var + 6; *tmp; tmp++)
313  *tmp = toupper(*tmp);
314 
315  pbx_builtin_setvar_helper(chan, var, args.value);
316  }
317  return 0;
318 }
static int tmp()
Definition: bt_open.c:389
#define var
Definition: ast_expr2f.c:614
const char * args
int value
Definition: syslog.c:37
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ AST_MODULE_INFO_STANDARD_DEPRECATED()

AST_MODULE_INFO_STANDARD_DEPRECATED ( ASTERISK_GPL_KEY  ,
"Simple Mysql Interface"   
)

Referenced by load_module().

◆ del_identifier()

static int del_identifier ( int  identifier,
int  identifier_type 
)
static

Definition at line 237 of file app_mysql.c.

References _mysql_ids_head, ast_free, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_MYSQL_id::entries, ast_MYSQL_id::identifier, ast_MYSQL_id::identifier_type, and LOG_WARNING.

Referenced by aMYSQL_clear(), and aMYSQL_disconnect().

238 {
239  struct ast_MYSQL_id *i;
240  struct MYSQLidshead *headp = &_mysql_ids_head;
241  int found = 0;
242 
243  if (AST_LIST_LOCK(headp)) {
244  ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
245  } else {
246  AST_LIST_TRAVERSE(headp, i, entries) {
247  if ((i->identifier == identifier) &&
248  (i->identifier_type == identifier_type)) {
249  AST_LIST_REMOVE(headp, i, entries);
250  ast_free(i);
251  found = 1;
252  break;
253  }
254  }
255  AST_LIST_UNLOCK(headp);
256  }
257 
258  if (found == 0) {
259  ast_log(LOG_WARNING, "Could not find identifier %d, identifier_type %d in list to delete\n", identifier, identifier_type);
260  return -1;
261  } else {
262  return 0;
263  }
264 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int identifier
Definition: app_mysql.c:127
struct MYSQLidshead _mysql_ids_head
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:855
#define ast_log
Definition: astobj2.c:42
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_free(a)
Definition: astmm.h:182
int identifier_type
Definition: app_mysql.c:126

◆ find_identifier()

static void* find_identifier ( int  identifier,
int  identifier_type 
)
static

Definition at line 185 of file app_mysql.c.

References _mysql_ids_head, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_MYSQL_id::data, ast_MYSQL_id::entries, ast_MYSQL_id::identifier, ast_MYSQL_id::identifier_type, LOG_WARNING, and NULL.

Referenced by aMYSQL_clear(), aMYSQL_disconnect(), aMYSQL_fetch(), aMYSQL_nextresult(), and aMYSQL_query().

186 {
187  struct MYSQLidshead *headp = &_mysql_ids_head;
188  struct ast_MYSQL_id *i;
189  void *res=NULL;
190  int found=0;
191 
192  if (AST_LIST_LOCK(headp)) {
193  ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
194  } else {
195  AST_LIST_TRAVERSE(headp, i, entries) {
196  if ((i->identifier == identifier) && (i->identifier_type == identifier_type)) {
197  found = 1;
198  res = i->data;
199  break;
200  }
201  }
202  if (!found) {
203  ast_log(LOG_WARNING, "Identifier %d, identifier_type %d not found in identifier list\n", identifier, identifier_type);
204  }
205  AST_LIST_UNLOCK(headp);
206  }
207 
208  return res;
209 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int identifier
Definition: app_mysql.c:127
struct MYSQLidshead _mysql_ids_head
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
struct ast_MYSQL_id::@1 entries
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
void * data
Definition: app_mysql.c:128
int identifier_type
Definition: app_mysql.c:126

◆ load_module()

static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 633 of file app_mysql.c.

References _mysql_ids_head, app, ast_config_destroy(), ast_config_load, AST_LIST_HEAD_INIT, ast_log, AST_MODULE_INFO_STANDARD_DEPRECATED(), ast_register_application, ast_true(), ast_variable_retrieve(), ASTERISK_GPL_KEY, autoclear, descrip, EMPTYSTRING, LOG_WARNING, MYSQL_CONFIG, MYSQL_CONFIG_OLD, MYSQL_exec(), NULLSTRING, NULLVALUE, nullvalue, and synopsis.

Referenced by load_values_config().

634 {
635  struct MYSQLidshead *headp = &_mysql_ids_head;
636  struct ast_flags config_flags = { 0 };
637  struct ast_config *cfg = ast_config_load(MYSQL_CONFIG, config_flags);
638  const char *temp;
639 
640  if (!cfg) {
641  /* Backwards compatibility ftw */
642  cfg = ast_config_load(MYSQL_CONFIG_OLD, config_flags);
643  }
644 
645  if (cfg) {
646  if ((temp = ast_variable_retrieve(cfg, "general", "nullvalue"))) {
647  if (!strcasecmp(temp, "nullstring")) {
649  } else if (!strcasecmp(temp, "emptystring")) {
651  } else if (!strcasecmp(temp, "null")) {
653  } else {
654  ast_log(LOG_WARNING, "Illegal value for 'nullvalue': '%s' (must be 'nullstring', 'null', or 'emptystring')\n", temp);
655  }
656  }
657  if ((temp = ast_variable_retrieve(cfg, "general", "autoclear")) && ast_true(temp)) {
658  autoclear = 1;
659  }
660  ast_config_destroy(cfg);
661  }
662 
663  AST_LIST_HEAD_INIT(headp);
665 }
static const char synopsis[]
Definition: app_mysql.c:64
#define LOG_WARNING
Definition: logger.h:274
#define MYSQL_CONFIG_OLD
Definition: app_mysql.c:107
struct MYSQLidshead _mysql_ids_head
static int autoclear
Definition: app_mysql.c:113
static int MYSQL_exec(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:561
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
#define ast_register_application(app, execute, synopsis, description)
Register an application.
Definition: module.h:610
static const char descrip[]
Definition: app_mysql.c:66
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define MYSQL_CONFIG
Definition: app_mysql.c:106
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
enum @0 nullvalue
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:625
Structure used to handle boolean flags.
Definition: utils.h:199
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
static const char app[]
Definition: app_mysql.c:62

◆ mysql_ds_destroy()

static void mysql_ds_destroy ( void *  data)
static

Definition at line 134 of file app_mysql.c.

References _mysql_ids_head, ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log, AST_MYSQL_ID_CONNID, AST_MYSQL_ID_RESID, ast_MYSQL_id::data, ast_MYSQL_id::entries, ast_MYSQL_id::identifier_type, LOG_WARNING, and ast_MYSQL_id::owner.

135 {
136  /* Destroy any IDs owned by the channel */
137  struct ast_MYSQL_id *i;
139  ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
140  } else {
142  if (i->owner == data) {
145  /* Drop connection */
146  mysql_close(i->data);
147  } else if (i->identifier_type == AST_MYSQL_ID_RESID) {
148  /* Drop result */
149  mysql_free_result(i->data);
150  }
151  ast_free(i);
152  }
153  }
156  }
157 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct MYSQLidshead _mysql_ids_head
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
#define ast_log
Definition: astobj2.c:42
#define AST_MYSQL_ID_CONNID
Definition: app_mysql.c:109
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
struct ast_channel * owner
Definition: app_mysql.c:125
struct ast_MYSQL_id::@1 entries
#define ast_free(a)
Definition: astmm.h:182
void * data
Definition: app_mysql.c:128
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
#define AST_MYSQL_ID_RESID
Definition: app_mysql.c:110
int identifier_type
Definition: app_mysql.c:126

◆ mysql_ds_fixup()

static void mysql_ds_fixup ( void *  data,
struct ast_channel oldchan,
struct ast_channel newchan 
)
static

Definition at line 159 of file app_mysql.c.

References _mysql_ids_head, ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log, AST_MYSQL_ID_CONNID, AST_MYSQL_ID_RESID, ast_MYSQL_id::data, ast_MYSQL_id::entries, ast_MYSQL_id::identifier_type, LOG_WARNING, and ast_MYSQL_id::owner.

160 {
161  /* Destroy any IDs owned by the channel */
162  struct ast_MYSQL_id *i;
164  ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
165  } else {
167  if (i->owner == data) {
170  /* Drop connection */
171  mysql_close(i->data);
172  } else if (i->identifier_type == AST_MYSQL_ID_RESID) {
173  /* Drop result */
174  mysql_free_result(i->data);
175  }
176  ast_free(i);
177  }
178  }
181  }
182 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct MYSQLidshead _mysql_ids_head
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
#define ast_log
Definition: astobj2.c:42
#define AST_MYSQL_ID_CONNID
Definition: app_mysql.c:109
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
struct ast_channel * owner
Definition: app_mysql.c:125
struct ast_MYSQL_id::@1 entries
#define ast_free(a)
Definition: astmm.h:182
void * data
Definition: app_mysql.c:128
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
#define AST_MYSQL_ID_RESID
Definition: app_mysql.c:110
int identifier_type
Definition: app_mysql.c:126

◆ MYSQL_exec()

static int MYSQL_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 561 of file app_mysql.c.

References _mysql_mutex, aMYSQL_clear(), aMYSQL_connect(), aMYSQL_disconnect(), aMYSQL_fetch(), aMYSQL_nextresult(), aMYSQL_query(), aMYSQL_set(), ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, autoclear, ast_datastore::data, LOG_WARNING, NULL, pbx_builtin_setvar_helper(), and result.

Referenced by load_module().

562 {
563  int result;
564  char sresult[10];
565 
566  ast_debug(5, "MYSQL: data=%s\n", data);
567 
568  if (!data) {
569  ast_log(LOG_WARNING, "MYSQL requires an argument (see manual)\n");
570  return -1;
571  }
572 
573  result = 0;
574 
575  if (autoclear) {
576  struct ast_datastore *mysql_store = NULL;
577 
578  ast_channel_lock(chan);
579  mysql_store = ast_channel_datastore_find(chan, &mysql_ds_info, NULL);
580  if (!mysql_store) {
581  if (!(mysql_store = ast_datastore_alloc(&mysql_ds_info, NULL))) {
582  ast_log(LOG_WARNING, "Unable to allocate new datastore.\n");
583  } else {
584  mysql_store->data = chan;
585  ast_channel_datastore_add(chan, mysql_store);
586  }
587  }
588  ast_channel_unlock(chan);
589  }
591 
592  if (strncasecmp("connect", data, strlen("connect")) == 0) {
593  result = aMYSQL_connect(chan, data);
594  } else if (strncasecmp("query", data, strlen("query")) == 0) {
595  result = aMYSQL_query(chan, data);
596  } else if (strncasecmp("nextresult", data, strlen("nextresult")) == 0) {
597  result = aMYSQL_nextresult(chan, data);
598  } else if (strncasecmp("fetch", data, strlen("fetch")) == 0) {
599  result = aMYSQL_fetch(chan, data);
600  } else if (strncasecmp("clear", data, strlen("clear")) == 0) {
601  result = aMYSQL_clear(chan, data);
602  } else if (strncasecmp("disconnect", data, strlen("disconnect")) == 0) {
603  result = aMYSQL_disconnect(chan, data);
604  } else if (strncasecmp("set", data, 3) == 0) {
605  result = aMYSQL_set(chan, data);
606  } else {
607  ast_log(LOG_WARNING, "Unknown argument to MYSQL application : %s\n", data);
608  result = -1;
609  }
610 
612 
613  snprintf(sresult, sizeof(sresult), "%d", result);
614  pbx_builtin_setvar_helper(chan, "MYSQL_STATUS", sresult);
615  return 0;
616 }
static ast_mutex_t _mysql_mutex
Definition: app_mysql.c:104
#define ast_channel_lock(chan)
Definition: channel.h:2945
static int aMYSQL_clear(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:525
static int aMYSQL_set(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:295
static int aMYSQL_query(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:390
#define LOG_WARNING
Definition: logger.h:274
static int aMYSQL_connect(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:321
static int aMYSQL_nextresult(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:432
#define ast_mutex_lock(a)
Definition: lock.h:187
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
static int autoclear
Definition: app_mysql.c:113
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static int aMYSQL_fetch(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:473
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void * data
Definition: app_mysql.c:128
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
void * data
Definition: datastore.h:70
static int aMYSQL_disconnect(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:543
static PGresult * result
Definition: cel_pgsql.c:88
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
static const struct ast_datastore_info mysql_ds_info
Definition: app_mysql.c:118
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ safe_scan_int()

static int safe_scan_int ( char **  data,
char *  delim,
int  def 
)
static

Definition at line 282 of file app_mysql.c.

References end, and strsep().

Referenced by aMYSQL_clear(), and aMYSQL_disconnect().

283 {
284  char *end;
285  int res = def;
286  char *s = strsep(data, delim);
287  if (s) {
288  res = strtol(s, &end, 10);
289  if (*end)
290  res = def; /* not an integer */
291  }
292  return res;
293 }
char * end
Definition: eagi_proxy.c:73
void * data
Definition: datastore.h:70
char * strsep(char **str, const char *delims)

◆ set_asterisk_int()

static int set_asterisk_int ( struct ast_channel chan,
char *  varname,
int  id 
)
static

Definition at line 266 of file app_mysql.c.

References ast_debug, id, and pbx_builtin_setvar_helper().

Referenced by add_identifier_and_set_asterisk_int(), and aMYSQL_fetch().

267 {
268  if (id >= 0) {
269  char s[12] = "";
270  snprintf(s, sizeof(s), "%d", id);
271  ast_debug(5, "MYSQL: setting var '%s' to value '%s'\n", varname, s);
272  pbx_builtin_setvar_helper(chan, varname, s);
273  }
274  return id;
275 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
enum queue_result id
Definition: app_queue.c:1507

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 618 of file app_mysql.c.

References app, and ast_unregister_application().

619 {
621 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static const char app[]
Definition: app_mysql.c:62

Variable Documentation

◆ _mysql_ids_head

struct MYSQLidshead _mysql_ids_head

◆ _mysql_mutex

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

Definition at line 104 of file app_mysql.c.

Referenced by MYSQL_exec().

◆ app

const char app[] = "MYSQL"
static

◆ ast_MYSQL_id

◆ autoclear

int autoclear = 0
static

Definition at line 113 of file app_mysql.c.

Referenced by load_module(), and MYSQL_exec().

◆ descrip

const char descrip[]
static

Definition at line 66 of file app_mysql.c.

Referenced by load_module().

◆ mysql_ds_info

const struct ast_datastore_info mysql_ds_info
static
Initial value:
= {
.type = "APP_ADDON_SQL_MYSQL",
.destroy = mysql_ds_destroy,
.chan_fixup = mysql_ds_fixup,
}
static void mysql_ds_destroy(void *data)
Definition: app_mysql.c:134
static void mysql_ds_fixup(void *data, struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: app_mysql.c:159

Definition at line 118 of file app_mysql.c.

◆ nullvalue

enum { ... } nullvalue

Referenced by aMYSQL_fetch(), and load_module().

◆ synopsis

const char synopsis[] = "Do several mySQLy things"
static